ItaniumCXXABI.cpp revision 8b418685e9e4f02f4eb2a76e1ec063e07552b68d
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 *EmitNullMemberPointer(const MemberPointerType *MPT); 78cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 79755d8497e39071aa24acc173ff07083e3256b8f8John McCall llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); 805808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, 815808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall CharUnits offset); 822d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith llvm::Constant *EmitMemberPointer(const APValue &MP, QualType MPT); 832d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD, 842d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith CharUnits ThisAdjustment); 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, 995f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<CanQualType> &ArgTys); 1004c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1014c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 1024c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType T, 1034c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner 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, 1345f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<CanQualType> &ArgTys); 1354c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1364c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 1374c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType T, 1384c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1395f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner 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 2182acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 21993d557bc1867b7d7b102f87290194b4be7932c92John McCall CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), 22093d557bc1867b7d7b102f87290194b4be7932c92John McCall FPT->isVariadic()); 22193d557bc1867b7d7b102f87290194b4be7932c92John McCall 2222acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner 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. 2622acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner 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. 3102acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner 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 3423023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall CGBuilderTy &Builder = CGF.Builder; 3433023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3443023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *SrcTy = 3453023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->getSubExpr()->getType()->getAs<MemberPointerType>(); 3463023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>(); 3473023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3483023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 3493023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl(); 3503023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3513023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall bool DerivedToBase = 3522de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall E->getCastKind() == CK_DerivedToBaseMemberPointer; 3533023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 354dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin const CXXRecordDecl *DerivedDecl; 3553023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall if (DerivedToBase) 356dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin DerivedDecl = SrcDecl; 3573023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall else 358dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin DerivedDecl = DestDecl; 3593023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 360d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Adj = 361d608cdb7c044365cf4e8764ade1e11e99c176078John McCall CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 362d608cdb7c044365cf4e8764ade1e11e99c176078John McCall E->path_begin(), 363d608cdb7c044365cf4e8764ade1e11e99c176078John McCall E->path_end()); 364d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (!Adj) return Src; 365875ab10245d3bf37252dd822aa1616bb0a391095John McCall 3660bab0cdab751248ca389a5592bcb70eac5d39260John McCall // For member data pointers, this is just a matter of adding the 3670bab0cdab751248ca389a5592bcb70eac5d39260John McCall // offset if the source is non-null. 3680bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (SrcTy->isMemberDataPointer()) { 3690bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Dst; 3700bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (DerivedToBase) 3710bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = Builder.CreateNSWSub(Src, Adj, "adj"); 3720bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 3730bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = Builder.CreateNSWAdd(Src, Adj, "adj"); 3740bab0cdab751248ca389a5592bcb70eac5d39260John McCall 3750bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Null check. 3760bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Null = llvm::Constant::getAllOnesValue(Src->getType()); 3770bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *IsNull = Builder.CreateICmpEQ(Src, Null, "memptr.isnull"); 3780bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateSelect(IsNull, Src, Dst); 3790bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 3800bab0cdab751248ca389a5592bcb70eac5d39260John McCall 381d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // The this-adjustment is left-shifted by 1 on ARM. 382d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (IsARM) { 383d608cdb7c044365cf4e8764ade1e11e99c176078John McCall uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue(); 384d608cdb7c044365cf4e8764ade1e11e99c176078John McCall Offset <<= 1; 385d608cdb7c044365cf4e8764ade1e11e99c176078John McCall Adj = llvm::ConstantInt::get(Adj->getType(), Offset); 386d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 387d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 388e14add4a275318e7a9cafd3a01f79fb15a5a08bcJohn McCall llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj"); 389d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *DstAdj; 390d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (DerivedToBase) 3910bab0cdab751248ca389a5592bcb70eac5d39260John McCall DstAdj = Builder.CreateNSWSub(SrcAdj, Adj, "adj"); 392d608cdb7c044365cf4e8764ade1e11e99c176078John McCall else 3930bab0cdab751248ca389a5592bcb70eac5d39260John McCall DstAdj = Builder.CreateNSWAdd(SrcAdj, Adj, "adj"); 394d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 395e14add4a275318e7a9cafd3a01f79fb15a5a08bcJohn McCall return Builder.CreateInsertValue(Src, DstAdj, 1); 3963023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall} 397cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 398cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallllvm::Constant * 3990bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 4002acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *ptrdiff_t = getPtrDiffTy(); 4010bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4020bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Itanium C++ ABI 2.3: 4030bab0cdab751248ca389a5592bcb70eac5d39260John McCall // A NULL pointer is represented as -1. 4040bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 4050bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::ConstantInt::get(ptrdiff_t, -1ULL, /*isSigned=*/true); 406d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 407d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0); 408d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Values[2] = { Zero, Zero }; 409c5cbb909e8a27deb8f1a2b6b7bf56a96051af81aChris Lattner return llvm::ConstantStruct::getAnon(Values); 410cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 411cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4125808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCallllvm::Constant * 4135808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCallItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 4145808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall CharUnits offset) { 4150bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Itanium C++ ABI 2.3: 4160bab0cdab751248ca389a5592bcb70eac5d39260John McCall // A pointer to data member is an offset from the base address of 4170bab0cdab751248ca389a5592bcb70eac5d39260John McCall // the class object containing it, represented as a ptrdiff_t 4185808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity()); 4190bab0cdab751248ca389a5592bcb70eac5d39260John McCall} 4200bab0cdab751248ca389a5592bcb70eac5d39260John McCall 421755d8497e39071aa24acc173ff07083e3256b8f8John McCallllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { 4222d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith return BuildMemberPointer(MD, CharUnits::Zero()); 4232d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith} 4242d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith 4252d6a5670465cb3f1d811695a9f23e372508240d2Richard Smithllvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD, 4262d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith CharUnits ThisAdjustment) { 427d608cdb7c044365cf4e8764ade1e11e99c176078John McCall assert(MD->isInstance() && "Member function must not be static!"); 428d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MD = MD->getCanonicalDecl(); 429875ab10245d3bf37252dd822aa1616bb0a391095John McCall 430d608cdb7c044365cf4e8764ade1e11e99c176078John McCall CodeGenTypes &Types = CGM.getTypes(); 4312acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *ptrdiff_t = getPtrDiffTy(); 432875ab10245d3bf37252dd822aa1616bb0a391095John McCall 433d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Get the function pointer (or index if this is a virtual function). 434d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *MemPtr[2]; 435d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (MD->isVirtual()) { 4361d2b31710539d705a3850c9fc3aa1804c2a5efeePeter Collingbourne uint64_t Index = CGM.getVTableContext().getMethodVTableIndex(MD); 437875ab10245d3bf37252dd822aa1616bb0a391095John McCall 4381246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck const ASTContext &Context = getContext(); 4391246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck CharUnits PointerWidth = 440bcfd1f55bfbb3e5944cd5e03d07b343e280838c4Douglas Gregor Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); 4411246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); 442d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 443d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (IsARM) { 444d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // ARM C++ ABI 3.2.1: 445d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // This ABI specifies that adj contains twice the this 446d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // adjustment, plus 1 if the member function is virtual. The 447d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // least significant bit of adj then makes exactly the same 448d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // discrimination as the least significant bit of ptr does for 449d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Itanium. 450d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset); 4512d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 4522d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith 2 * ThisAdjustment.getQuantity() + 1); 453d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 454d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Itanium C++ ABI 2.3: 455d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // For a virtual function, [the pointer field] is 1 plus the 456d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // virtual table offset (in bytes) of the function, 457d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // represented as a ptrdiff_t. 458d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1); 4592d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 4602d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith ThisAdjustment.getQuantity()); 461d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 462d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 463755d8497e39071aa24acc173ff07083e3256b8f8John McCall const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 4642acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *Ty; 465755d8497e39071aa24acc173ff07083e3256b8f8John McCall // Check whether the function has a computable LLVM signature. 466f742eb0196e1b25c0b71e91da4a2b856d16a1dabChris Lattner if (Types.isFuncTypeConvertible(FPT)) { 467755d8497e39071aa24acc173ff07083e3256b8f8John McCall // The function has a computable LLVM signature; use the correct type. 468755d8497e39071aa24acc173ff07083e3256b8f8John McCall Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), 469755d8497e39071aa24acc173ff07083e3256b8f8John McCall FPT->isVariadic()); 470d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 471755d8497e39071aa24acc173ff07083e3256b8f8John McCall // Use an arbitrary non-function type to tell GetAddrOfFunction that the 472755d8497e39071aa24acc173ff07083e3256b8f8John McCall // function type is incomplete. 473755d8497e39071aa24acc173ff07083e3256b8f8John McCall Ty = ptrdiff_t; 474d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 475755d8497e39071aa24acc173ff07083e3256b8f8John McCall llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); 476d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 477379b5155b4566f63679e1da6b0ceb5fdfa2aec6dJohn McCall MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t); 4782d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, (IsARM ? 2 : 1) * 4792d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith ThisAdjustment.getQuantity()); 480d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 481d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 482c5cbb909e8a27deb8f1a2b6b7bf56a96051af81aChris Lattner return llvm::ConstantStruct::getAnon(MemPtr); 483875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 484875ab10245d3bf37252dd822aa1616bb0a391095John McCall 4852d6a5670465cb3f1d811695a9f23e372508240d2Richard Smithllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP, 4862d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith QualType MPType) { 4872d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith const MemberPointerType *MPT = MPType->castAs<MemberPointerType>(); 4882d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith const ValueDecl *MPD = MP.getMemberPointerDecl(); 4892d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith if (!MPD) 4902d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith return EmitNullMemberPointer(MPT); 4912d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith 4922d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith // Compute the this-adjustment. 4932d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith CharUnits ThisAdjustment = CharUnits::Zero(); 4942d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath(); 4952d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith bool DerivedMember = MP.isMemberPointerToDerivedMember(); 4962d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext()); 4972d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith for (unsigned I = 0, N = Path.size(); I != N; ++I) { 4982d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith const CXXRecordDecl *Base = RD; 4992d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith const CXXRecordDecl *Derived = Path[I]; 5002d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith if (DerivedMember) 5012d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith std::swap(Base, Derived); 5022d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith ThisAdjustment += 5032d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base); 5042d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith RD = Path[I]; 5052d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith } 5062d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith if (DerivedMember) 5072d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith ThisAdjustment = -ThisAdjustment; 5082d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith 5092d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) 5102d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith return BuildMemberPointer(MD, ThisAdjustment); 5112d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith 5122d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith CharUnits FieldOffset = 5132d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); 5142d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset); 5152d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith} 5162d6a5670465cb3f1d811695a9f23e372508240d2Richard Smith 517e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// The comparison algorithm is pretty easy: the member pointers are 518e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// the same if they're either bitwise identical *or* both null. 519e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// 520e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// ARM is different here only because null-ness is more complicated. 521e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 5220bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 5230bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *L, 5240bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *R, 5250bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT, 5260bab0cdab751248ca389a5592bcb70eac5d39260John McCall bool Inequality) { 527e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 528e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 529e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::ICmpInst::Predicate Eq; 530e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Instruction::BinaryOps And, Or; 531e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (Inequality) { 532e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_NE; 533e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::Or; 534e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::And; 535e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } else { 536e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_EQ; 537e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::And; 538e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::Or; 539e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 540e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 5410bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Member data pointers are easy because there's a unique null 5420bab0cdab751248ca389a5592bcb70eac5d39260John McCall // value, so it just comes down to bitwise equality. 5430bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 5440bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateICmp(Eq, L, R); 5450bab0cdab751248ca389a5592bcb70eac5d39260John McCall 5460bab0cdab751248ca389a5592bcb70eac5d39260John McCall // For member function pointers, the tautologies are more complex. 5470bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The Itanium tautology is: 548de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj)) 5490bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The ARM tautology is: 550de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L == R) <==> (L.ptr == R.ptr && 551de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L.adj == R.adj || 552de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) 5530bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The inequality tautologies have exactly the same structure, except 5540bab0cdab751248ca389a5592bcb70eac5d39260John McCall // applying De Morgan's laws. 5550bab0cdab751248ca389a5592bcb70eac5d39260John McCall 5560bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); 5570bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); 5580bab0cdab751248ca389a5592bcb70eac5d39260John McCall 559e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.ptr == R.ptr. This must always be 560e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true for equality to hold. 561e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); 562e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 563e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition, together with the assumption that L.ptr == R.ptr, 564e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // tests whether the pointers are both null. ARM imposes an extra 565e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // condition. 566e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); 567e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); 568e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 569e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.adj == R.adj. If this isn't 570e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true, the pointers are unequal unless they're both null. 571d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); 572d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); 573e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); 574e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 575e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Null member function pointers on ARM clear the low bit of Adj, 576e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // so the zero condition has to check that neither low bit is set. 577e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 578e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); 579e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 580e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Compute (l.adj | r.adj) & 1 and test it against zero. 581e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); 582e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); 583e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, 584e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "cmp.or.adj"); 585e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); 586e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 587e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 588e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Tie together all our conditions. 589e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); 590e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Result = Builder.CreateBinOp(And, PtrEq, Result, 591e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Inequality ? "memptr.ne" : "memptr.eq"); 592e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 593e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 594e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 595e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 5960bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 5970bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *MemPtr, 5980bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT) { 599e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 6000bab0cdab751248ca389a5592bcb70eac5d39260John McCall 6010bab0cdab751248ca389a5592bcb70eac5d39260John McCall /// For member data pointers, this is just a check against -1. 6020bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) { 6030bab0cdab751248ca389a5592bcb70eac5d39260John McCall assert(MemPtr->getType() == getPtrDiffTy()); 6040bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *NegativeOne = 6050bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant::getAllOnesValue(MemPtr->getType()); 6060bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); 6070bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 608e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 609db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // In Itanium, a member function pointer is not null if 'ptr' is not null. 610d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); 611e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 612e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); 613e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); 614e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 615db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // On ARM, a member function pointer is also non-null if the low bit of 'adj' 616db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // (the virtual bit) is set. 617e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 618e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); 619d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); 620e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); 621db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, 622db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar "memptr.isvirtual"); 623db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar Result = Builder.CreateOr(Result, IsVirtual); 624e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 625e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 626e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 627e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 628875ab10245d3bf37252dd822aa1616bb0a391095John McCall 629f16aa103d3afd42fbca2ab346f191bf745cec092John McCall/// The Itanium ABI requires non-zero initialization only for data 630f16aa103d3afd42fbca2ab346f191bf745cec092John McCall/// member pointers, for which '0' is a valid offset. 631f16aa103d3afd42fbca2ab346f191bf745cec092John McCallbool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 632f16aa103d3afd42fbca2ab346f191bf745cec092John McCall return MPT->getPointeeType()->isFunctionType(); 633cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 6344c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6354c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The generic ABI passes 'this', plus a VTT if it's initializing a 6364c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// base subobject. 6374c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 6384c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType Type, 6394c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 6405f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<CanQualType> &ArgTys) { 6419cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 6424c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6434c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // 'this' is already there. 6444c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6454c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need to add a VTT parameter (which has type void **). 6464c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0) 6474c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 6484c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 6494c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6504c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The ARM ABI does the same as the Itanium ABI, but returns 'this'. 6514c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 6524c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType Type, 6534c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 6545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<CanQualType> &ArgTys) { 6554c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys); 6564c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ResTy = ArgTys[0]; 6574c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 6584c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6594c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The generic ABI passes 'this', plus a VTT if it's destroying a 6604c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// base subobject. 6614c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 6624c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType Type, 6634c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 6645f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<CanQualType> &ArgTys) { 6659cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 6664c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6674c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // 'this' is already there. 6684c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6694c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need to add a VTT parameter (which has type void **). 6704c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0) 6714c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 6724c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 6734c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6744c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The ARM ABI does the same as the Itanium ABI, but returns 'this' 6754c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// for non-deleting destructors. 6764c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 6774c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType Type, 6784c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 6795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVectorImpl<CanQualType> &ArgTys) { 6804c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys); 6814c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6824c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type != Dtor_Deleting) 6834c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ResTy = ArgTys[0]; 6844c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 6854c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6864c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 6874c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 6884c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params) { 6894c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Create the 'this' variable. 6904c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall BuildThisParam(CGF, Params); 6914c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6924c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 6934c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall assert(MD->isInstance()); 6944c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6954c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need a VTT parameter as well. 6964c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { 6979cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 6984c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6994c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // FIXME: avoid the fake decl 7004c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType T = Context.getPointerType(Context.VoidPtrTy); 7014c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ImplicitParamDecl *VTTDecl 7024c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), 7034c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall &Context.Idents.get("vtt"), T); 704d26bc76c98006609002d9930f8840490e88ac5b5John McCall Params.push_back(VTTDecl); 7054c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall getVTTDecl(CGF) = VTTDecl; 7064c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 7074c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7084c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7094c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 7104c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 7114c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params) { 7124c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params); 7134c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7144c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Return 'this' from certain constructors and destructors. 7154c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (HasThisReturn(CGF.CurGD)) 716d26bc76c98006609002d9930f8840490e88ac5b5John McCall ResTy = Params[0]->getType(); 7174c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7184c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7194c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 7204c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the 'this' slot. 7214c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall EmitThisParam(CGF); 7224c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7234c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the 'vtt' slot if needed. 7244c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (getVTTDecl(CGF)) { 7254c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall getVTTValue(CGF) 7264c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)), 7274c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall "vtt"); 7284c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 7294c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7304c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7314c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 7324c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); 7334c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7344c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the return slot to 'this' at the start of the 7354c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// function. 7364c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (HasThisReturn(CGF.CurGD)) 7374c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue); 7384c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7394c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7404c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 7414c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall RValue RV, QualType ResultType) { 7424c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) 7434c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); 7444c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7454c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Destructor thunks in the ARM ABI have indeterminate results. 7462acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *T = 7474c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType(); 7484c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall RValue Undef = RValue::get(llvm::UndefValue::get(T)); 7494c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); 7504c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7521e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall/************************** Array allocation cookies **************************/ 7531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7546ec278d1a354517e20f13a877481453ee7940c78John McCallbool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) { 7556ec278d1a354517e20f13a877481453ee7940c78John McCall // If the class's usual deallocation function takes two arguments, 7566ec278d1a354517e20f13a877481453ee7940c78John McCall // it needs a cookie. 7576ec278d1a354517e20f13a877481453ee7940c78John McCall if (expr->doesUsualArrayDeleteWantSize()) 7586ec278d1a354517e20f13a877481453ee7940c78John McCall return true; 7596ec278d1a354517e20f13a877481453ee7940c78John McCall 760f85e193739c953358c865005855253af4f68a497John McCall // Automatic Reference Counting: 761f85e193739c953358c865005855253af4f68a497John McCall // We need an array cookie for pointers with strong or weak lifetime. 762f85e193739c953358c865005855253af4f68a497John McCall QualType AllocatedType = expr->getAllocatedType(); 763f85e193739c953358c865005855253af4f68a497John McCall if (getContext().getLangOptions().ObjCAutoRefCount && 764f85e193739c953358c865005855253af4f68a497John McCall AllocatedType->isObjCLifetimeType()) { 765f85e193739c953358c865005855253af4f68a497John McCall switch (AllocatedType.getObjCLifetime()) { 766f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_None: 767f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_ExplicitNone: 768f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Autoreleasing: 769f85e193739c953358c865005855253af4f68a497John McCall return false; 770f85e193739c953358c865005855253af4f68a497John McCall 771f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Strong: 772f85e193739c953358c865005855253af4f68a497John McCall case Qualifiers::OCL_Weak: 773f85e193739c953358c865005855253af4f68a497John McCall return true; 774f85e193739c953358c865005855253af4f68a497John McCall } 775f85e193739c953358c865005855253af4f68a497John McCall } 776f85e193739c953358c865005855253af4f68a497John McCall 7776ec278d1a354517e20f13a877481453ee7940c78John McCall // Otherwise, if the class has a non-trivial destructor, it always 7786ec278d1a354517e20f13a877481453ee7940c78John McCall // needs a cookie. 7796ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXRecordDecl *record = 780f85e193739c953358c865005855253af4f68a497John McCall AllocatedType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 7816ec278d1a354517e20f13a877481453ee7940c78John McCall return (record && !record->hasTrivialDestructor()); 7826ec278d1a354517e20f13a877481453ee7940c78John McCall} 7831e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7846ec278d1a354517e20f13a877481453ee7940c78John McCallbool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr, 7856ec278d1a354517e20f13a877481453ee7940c78John McCall QualType elementType) { 7861e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If the class's usual deallocation function takes two arguments, 7876ec278d1a354517e20f13a877481453ee7940c78John McCall // it needs a cookie. 7886ec278d1a354517e20f13a877481453ee7940c78John McCall if (expr->doesUsualArrayDeleteWantSize()) 7896ec278d1a354517e20f13a877481453ee7940c78John McCall return true; 7906ec278d1a354517e20f13a877481453ee7940c78John McCall 79191873b72bf01b7170f80154f3118300ff2eacd34Eli Friedman return elementType.isDestructedType(); 7921e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 7931e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7946ec278d1a354517e20f13a877481453ee7940c78John McCallCharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 7956ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr)) 7961e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CharUnits::Zero(); 7971e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7986ec278d1a354517e20f13a877481453ee7940c78John McCall // Padding is the maximum of sizeof(size_t) and alignof(elementType) 7999cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 8001e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), 8016ec278d1a354517e20f13a877481453ee7940c78John McCall Ctx.getTypeAlignInChars(expr->getAllocatedType())); 8021e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8031e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8041e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallllvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 8051e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 8061e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 8076ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 8081e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType) { 8096ec278d1a354517e20f13a877481453ee7940c78John McCall assert(NeedsArrayCookie(expr)); 8101e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8111e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 8121e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8139cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 8141e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType SizeTy = Ctx.getSizeType(); 8151e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy); 8161e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8171e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The size of the cookie. 8181e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieSize = 8191e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); 8201e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8211e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Compute an offset to the cookie. 8221e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *CookiePtr = NewPtr; 8231e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieOffset = CookieSize - SizeSize; 8241e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall if (!CookieOffset.isZero()) 8251e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr, 8261e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieOffset.getQuantity()); 8271e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8281e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Write the number of elements into the appropriate slot. 8291e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr 8301e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall = CGF.Builder.CreateBitCast(CookiePtr, 8311e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.ConvertType(SizeTy)->getPointerTo(AS)); 8321e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(NumElements, NumElementsPtr); 8331e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8341e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Finally, compute a pointer to the actual data buffer by skipping 8351e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // over the cookie completely. 8361e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 8371e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize.getQuantity()); 8381e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8391e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8401e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallvoid ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 8411e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *Ptr, 8426ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 8431e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, 8441e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&NumElements, 8451e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, 8461e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits &CookieSize) { 8471e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Derive a char* in the same address space as the pointer. 8481e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 8492acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 8501e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If we don't need an array cookie, bail out early. 8526ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr, ElementType)) { 8531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 8541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = 0; 8551e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = CharUnits::Zero(); 8561e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return; 8571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall } 8581e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8599cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType SizeTy = getContext().getSizeType(); 8609cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 8612acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 8621e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8631e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize 8649cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType)); 8651e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8661e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits NumElementsOffset = CookieSize - SizeSize; 8671e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8681e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Compute the allocated pointer. 8691e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 8701e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 8711e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall -CookieSize.getQuantity()); 8721e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8731e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr = AllocPtr; 8741e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall if (!NumElementsOffset.isZero()) 8751e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 8761e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr, 8771e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsOffset.getQuantity()); 8781e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 8791e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 8801e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 8811e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8821e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8836ec278d1a354517e20f13a877481453ee7940c78John McCallCharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 8846ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr)) 8851e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CharUnits::Zero(); 8861e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8871e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // On ARM, the cookie is always: 8881e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // struct array_cookie { 8891e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // std::size_t element_size; // element_size != 0 8901e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // std::size_t element_count; 8911e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // }; 8921e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // TODO: what should we do if the allocated type actually wants 8931e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // greater alignment? 8941e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2; 8951e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8961e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8971e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallllvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 8981e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 8991e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 9006ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 9011e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType) { 9026ec278d1a354517e20f13a877481453ee7940c78John McCall assert(NeedsArrayCookie(expr)); 9031e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9041e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // NewPtr is a char*. 9051e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9061e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 9071e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9089cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 9091e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType()); 9102acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::IntegerType *SizeTy = 9111e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType())); 9121e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9131e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The cookie is always at the start of the buffer. 9141e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *CookiePtr = NewPtr; 9151e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9161e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The first element is the element size. 9171e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS)); 9181e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy, 9191e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall Ctx.getTypeSizeInChars(ElementType).getQuantity()); 9201e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(ElementSize, CookiePtr); 9211e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9221e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The second element is the element count. 9231e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1); 9241e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(NumElements, CookiePtr); 9251e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9261e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Finally, compute a pointer to the actual data buffer by skipping 9271e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // over the cookie completely. 9281e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieSize = 2 * SizeSize; 9291e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 9301e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize.getQuantity()); 9311e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9321e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9331e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallvoid ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 9341e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *Ptr, 9356ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 9361e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, 9371e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&NumElements, 9381e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, 9391e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits &CookieSize) { 9401e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Derive a char* in the same address space as the pointer. 9411e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 9422acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 9431e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9441e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If we don't need an array cookie, bail out early. 9456ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr, ElementType)) { 9461e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 9471e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = 0; 9481e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = CharUnits::Zero(); 9491e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return; 9501e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall } 9511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9529cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType SizeTy = getContext().getSizeType(); 9539cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 9542acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 9551e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9561e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The cookie size is always 2 * sizeof(size_t). 9571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = 2 * SizeSize; 9581e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9591e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The allocated pointer is the input ptr, minus that amount. 9601e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 9611e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 9621e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall -CookieSize.getQuantity()); 9631e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9641e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The number of elements is at offset sizeof(size_t) relative to that. 9651e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr 9661e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 9671e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall SizeSize.getQuantity()); 9681e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 9691e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 9701e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 9711e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9721e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9735cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/*********************** Static local initialization **************************/ 9745cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 9755cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM, 9769cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy) { 9775cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // int __cxa_guard_acquire(__guard *guard_object); 9782acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 9795cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), 980da549e8995c447542d5631b8b67fcc3a9582797aJay Foad GuardPtrTy, /*isVarArg=*/false); 9815cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 9825cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 9835cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 9845cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 9855cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM, 9869cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy) { 9875cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // void __cxa_guard_release(__guard *guard_object); 9882acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 9898b418685e9e4f02f4eb2a76e1ec063e07552b68dChris Lattner llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false); 9905cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 9915cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 9925cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 9935cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 9945cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardAbortFn(CodeGenModule &CGM, 9959cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy) { 9965cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // void __cxa_guard_abort(__guard *guard_object); 9972acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 9988b418685e9e4f02f4eb2a76e1ec063e07552b68dChris Lattner llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false); 9995cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10005cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 10015cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10025cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10035cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallnamespace { 10045cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall struct CallGuardAbort : EHScopeStack::Cleanup { 10055cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::GlobalVariable *Guard; 10065cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} 10075cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 1008ad346f4f678ab1c3222425641d851dc63e9dfa1aJohn McCall void Emit(CodeGenFunction &CGF, Flags flags) { 10095cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard) 10105cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall ->setDoesNotThrow(); 10115cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 10125cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall }; 10135cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10145cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10155cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// The ARM code here follows the Itanium code closely enough that we 10165cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// just special-case it at particular places. 10173030eb82593097502469a8b3fc26112c79c75605John McCallvoid ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, 10183030eb82593097502469a8b3fc26112c79c75605John McCall const VarDecl &D, 10193030eb82593097502469a8b3fc26112c79c75605John McCall llvm::GlobalVariable *GV) { 10205cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGBuilderTy &Builder = CGF.Builder; 10213030eb82593097502469a8b3fc26112c79c75605John McCall 10223030eb82593097502469a8b3fc26112c79c75605John McCall // We only need to use thread-safe statics for local variables; 10233030eb82593097502469a8b3fc26112c79c75605John McCall // global initialization is always single-threaded. 10240502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall bool threadsafe = 10250502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall (getContext().getLangOptions().ThreadsafeStatics && D.isLocalVarDecl()); 1026173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson 10272acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::IntegerType *GuardTy; 1028173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson 1029173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // If we have a global variable with internal linkage and thread-safe statics 1030173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // are disabled, we can just let the guard variable be of type i8. 10310502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall bool useInt8GuardVariable = !threadsafe && GV->hasInternalLinkage(); 10320502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (useInt8GuardVariable) { 10330502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall GuardTy = CGF.Int8Ty; 10340502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall } else { 1035173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. 10360502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall GuardTy = (IsARM ? CGF.Int32Ty : CGF.Int64Ty); 1037173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson } 10389cbe4f0ba01ec304e1e3d071c071f7bca33631c0Chris Lattner llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo(); 10395cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10405cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Create the guard variable. 1041f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<256> GuardVName; 1042f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola llvm::raw_svector_ostream Out(GuardVName); 1043f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola getMangleContext().mangleItaniumGuardVariable(&D, Out); 1044f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola Out.flush(); 1045112c967bd5c862a0f5d7913aa06700c048807db8John McCall 10463030eb82593097502469a8b3fc26112c79c75605John McCall // Just absorb linkage and visibility from the variable. 10475cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::GlobalVariable *GuardVariable = 10485cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall new llvm::GlobalVariable(CGM.getModule(), GuardTy, 10493030eb82593097502469a8b3fc26112c79c75605John McCall false, GV->getLinkage(), 10505cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::ConstantInt::get(GuardTy, 0), 10515cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall GuardVName.str()); 1052112c967bd5c862a0f5d7913aa06700c048807db8John McCall GuardVariable->setVisibility(GV->getVisibility()); 10535cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10545cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Test whether the variable has completed initialization. 10555cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *IsInitialized; 10565cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10575cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ARM C++ ABI 3.2.3.1: 10585cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // To support the potential use of initialization guard variables 10595cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // as semaphores that are the target of ARM SWP and LDREX/STREX 10605cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // synchronizing instructions we define a static initialization 10615cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // guard variable to be a 4-byte aligned, 4- byte word with the 10625cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // following inline access protocol. 10635cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // #define INITIALIZED 1 10645cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if ((obj_guard & INITIALIZED) != INITIALIZED) { 10655cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if (__cxa_guard_acquire(&obj_guard)) 10665cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... 10675cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 10680502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (IsARM && !useInt8GuardVariable) { 10695cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V = Builder.CreateLoad(GuardVariable); 10705cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall V = Builder.CreateAnd(V, Builder.getInt32(1)); 10715cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 10725cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10735cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Itanium C++ ABI 3.3.2: 10745cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // The following is pseudo-code showing how these functions can be used: 10755cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if (obj_guard.first_byte == 0) { 10765cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if ( __cxa_guard_acquire (&obj_guard) ) { 10775cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // try { 10785cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... initialize the object ...; 10795cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } catch (...) { 10805cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // __cxa_guard_abort (&obj_guard); 10815cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // throw; 10825cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 10835cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... queue object destructor with __cxa_atexit() ...; 10845cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // __cxa_guard_release (&obj_guard); 10855cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 10865cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 10875cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } else { 10885cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Load the first byte of the guard variable. 10892acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *PtrTy = Builder.getInt8PtrTy(); 1090eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman llvm::LoadInst *LI = 1091578faa837b552403e2002b97fdfbfde14f2448e5Benjamin Kramer Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy)); 1092eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman LI->setAlignment(1); 1093eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman 1094eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman // Itanium ABI: 1095eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman // An implementation supporting thread-safety on multiprocessor 1096eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman // systems must also guarantee that references to the initialized 1097eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman // object do not occur before the load of the initialization flag. 1098eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman // 1099eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman // In LLVM, we do this by marking the load Acquire. 1100eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman if (threadsafe) 1101eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman LI->setAtomic(llvm::Acquire); 1102eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman 1103eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman IsInitialized = Builder.CreateIsNull(LI, "guard.uninitialized"); 11045cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11055cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11065cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); 11075cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); 11085cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11095cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Check if the first byte of the guard variable is zero. 1110eb43f4a8f133c2bc510ae136a556e92b68a6ff44Eli Friedman Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock); 11115cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11125cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(InitCheckBlock); 11135cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11145cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Variables used when coping with thread-safe statics and exceptions. 11150502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (threadsafe) { 11165cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_acquire. 11175cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V 11185cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable); 11195cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11205cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); 11215cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11225cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 11235cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall InitBlock, EndBlock); 11245cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11255cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_abort along the exceptional edge. 11265cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); 11275cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11285cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(InitBlock); 11295cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11305cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11315cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Emit the initializer and add a global destructor if appropriate. 11325cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitCXXGlobalVarDeclInit(D, GV); 11335cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11340502a224984a26087ea4d64e8e5d2dd4dca432f6John McCall if (threadsafe) { 11355cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Pop the guard-abort cleanup if we pushed one. 11365cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.PopCleanupBlock(); 11375cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11385cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_release. This cannot throw. 11395cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable); 11405cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } else { 11415cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable); 11425cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11435cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11445cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(EndBlock); 11455cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 1146