ItaniumCXXABI.cpp revision 173d51286bcaff4b6b76eebf6542d3b1311142e2
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> 270bab0cdab751248ca389a5592bcb70eac5d39260John McCall#include <llvm/Target/TargetData.h> 2893d557bc1867b7d7b102f87290194b4be7932c92John McCall#include <llvm/Value.h> 293a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 303a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davisusing namespace clang; 3193d557bc1867b7d7b102f87290194b4be7932c92John McCallusing namespace CodeGen; 323a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 333a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davisnamespace { 34071cc7deffad608165b1ddd5263e8bf181861520Charles Davisclass ItaniumCXXABI : public CodeGen::CGCXXABI { 350bab0cdab751248ca389a5592bcb70eac5d39260John McCallprivate: 360bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::IntegerType *PtrDiffTy; 3793d557bc1867b7d7b102f87290194b4be7932c92John McCallprotected: 38babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall bool IsARM; 390bab0cdab751248ca389a5592bcb70eac5d39260John McCall 400bab0cdab751248ca389a5592bcb70eac5d39260John McCall // It's a little silly for us to cache this. 410bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::IntegerType *getPtrDiffTy() { 420bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (!PtrDiffTy) { 439cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType T = getContext().getPointerDiffType(); 440bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::Type *Ty = CGM.getTypes().ConvertTypeRecursive(T); 450bab0cdab751248ca389a5592bcb70eac5d39260John McCall PtrDiffTy = cast<llvm::IntegerType>(Ty); 460bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 470bab0cdab751248ca389a5592bcb70eac5d39260John McCall return PtrDiffTy; 480bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 490bab0cdab751248ca389a5592bcb70eac5d39260John McCall 506ec278d1a354517e20f13a877481453ee7940c78John McCall bool NeedsArrayCookie(const CXXNewExpr *expr); 516ec278d1a354517e20f13a877481453ee7940c78John McCall bool NeedsArrayCookie(const CXXDeleteExpr *expr, 526ec278d1a354517e20f13a877481453ee7940c78John McCall QualType elementType); 531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 543a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davispublic: 55babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) : 5614110477887e3dc168ffc6c191e72d705051f99ePeter Collingbourne CGCXXABI(CGM), PtrDiffTy(0), IsARM(IsARM) { } 5793d557bc1867b7d7b102f87290194b4be7932c92John McCall 58f16aa103d3afd42fbca2ab346f191bf745cec092John McCall bool isZeroInitializable(const MemberPointerType *MPT); 59cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 600bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT); 610bab0cdab751248ca389a5592bcb70eac5d39260John McCall 6293d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 6393d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *&This, 6493d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *MemFnPtr, 6593d557bc1867b7d7b102f87290194b4be7932c92John McCall const MemberPointerType *MPT); 663023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 676c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, 686c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *Base, 696c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *MemPtr, 706c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall const MemberPointerType *MPT); 716c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 720bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *EmitMemberPointerConversion(CodeGenFunction &CGF, 730bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E, 740bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Src); 75cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 760bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *EmitMemberPointerConversion(llvm::Constant *C, 770bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E); 78cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 790bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT); 80cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 81755d8497e39071aa24acc173ff07083e3256b8f8John McCall llvm::Constant *EmitMemberPointer(const CXXMethodDecl *MD); 825808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT, 835808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall CharUnits offset); 84875ab10245d3bf37252dd822aa1616bb0a391095John McCall 850bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, 860bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *L, 870bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *R, 880bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT, 890bab0cdab751248ca389a5592bcb70eac5d39260John McCall bool Inequality); 90e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 910bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 920bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Addr, 930bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT); 944c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 954c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 964c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType T, 974c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 984c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 994c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1004c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 1014c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType T, 1024c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1034c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 1044c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1054c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildInstanceFunctionParams(CodeGenFunction &CGF, 1064c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 1074c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params); 1084c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1094c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 1101e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 1116ec278d1a354517e20f13a877481453ee7940c78John McCall CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 1121e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 1131e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 1141e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 1156ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 1161e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType); 1171e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 1186ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 1191e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, llvm::Value *&NumElements, 1201e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, CharUnits &CookieSize); 1215cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 1223030eb82593097502469a8b3fc26112c79c75605John McCall void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, 1233030eb82593097502469a8b3fc26112c79c75605John McCall llvm::GlobalVariable *DeclPtr); 1243a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis}; 125ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall 126ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallclass ARMCXXABI : public ItaniumCXXABI { 127ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallpublic: 128babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} 1294c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1304c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildConstructorSignature(const CXXConstructorDecl *Ctor, 1314c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType T, 1324c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1334c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 1344c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1354c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildDestructorSignature(const CXXDestructorDecl *Dtor, 1364c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType T, 1374c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 1384c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys); 1394c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1404c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void BuildInstanceFunctionParams(CodeGenFunction &CGF, 1414c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 1424c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params); 1434c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1444c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void EmitInstanceFunctionProlog(CodeGenFunction &CGF); 1454c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1464c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); 1474c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1486ec278d1a354517e20f13a877481453ee7940c78John McCall CharUnits GetArrayCookieSize(const CXXNewExpr *expr); 1491e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *InitializeArrayCookie(CodeGenFunction &CGF, 1501e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 1511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 1526ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 1531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType); 1541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall void ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *Ptr, 1556ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 1561e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, llvm::Value *&NumElements, 1571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, CharUnits &CookieSize); 1584c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 1594c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallprivate: 1604c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// \brief Returns true if the given instance method is one of the 1614c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// kinds that the ARM ABI says returns 'this'. 1624c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall static bool HasThisReturn(GlobalDecl GD) { 1634c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); 1644c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) || 1654c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall (isa<CXXConstructorDecl>(MD))); 1664c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 167ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall}; 1683a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis} 1693a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 170071cc7deffad608165b1ddd5263e8bf181861520Charles DavisCodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { 1713a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis return new ItaniumCXXABI(CGM); 1723a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis} 1733a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 174ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallCodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) { 175ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall return new ARMCXXABI(CGM); 176ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall} 177ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall 1780bab0cdab751248ca389a5592bcb70eac5d39260John McCallconst llvm::Type * 1790bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { 1800bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 1810bab0cdab751248ca389a5592bcb70eac5d39260John McCall return getPtrDiffTy(); 1820bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 1830bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::StructType::get(CGM.getLLVMContext(), 1840bab0cdab751248ca389a5592bcb70eac5d39260John McCall getPtrDiffTy(), getPtrDiffTy(), NULL); 185875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 186875ab10245d3bf37252dd822aa1616bb0a391095John McCall 187babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the Itanium and ARM ABIs, method pointers have the form: 188babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr; 189babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 190babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the Itanium ABI: 191babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - method pointers are virtual if (memptr.ptr & 1) is nonzero 192babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the this-adjustment is (memptr.adj) 193babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the virtual offset is (memptr.ptr - 1) 194babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 195babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the ARM ABI: 196babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - method pointers are virtual if (memptr.adj & 1) is nonzero 197babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the this-adjustment is (memptr.adj >> 1) 198babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the virtual offset is (memptr.ptr) 199babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// ARM uses 'adj' for the virtual flag because Thumb functions 200babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// may be only single-byte aligned. 201babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 202babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// If the member is virtual, the adjusted 'this' pointer points 203babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// to a vtable pointer from which the virtual offset is applied. 204babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 205babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// If the member is non-virtual, memptr.ptr is the address of 206babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// the function to call. 20793d557bc1867b7d7b102f87290194b4be7932c92John McCallllvm::Value * 20893d557bc1867b7d7b102f87290194b4be7932c92John McCallItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 20993d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *&This, 21093d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *MemFnPtr, 21193d557bc1867b7d7b102f87290194b4be7932c92John McCall const MemberPointerType *MPT) { 21293d557bc1867b7d7b102f87290194b4be7932c92John McCall CGBuilderTy &Builder = CGF.Builder; 21393d557bc1867b7d7b102f87290194b4be7932c92John McCall 21493d557bc1867b7d7b102f87290194b4be7932c92John McCall const FunctionProtoType *FPT = 21593d557bc1867b7d7b102f87290194b4be7932c92John McCall MPT->getPointeeType()->getAs<FunctionProtoType>(); 21693d557bc1867b7d7b102f87290194b4be7932c92John McCall const CXXRecordDecl *RD = 21793d557bc1867b7d7b102f87290194b4be7932c92John McCall cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 21893d557bc1867b7d7b102f87290194b4be7932c92John McCall 21993d557bc1867b7d7b102f87290194b4be7932c92John McCall const llvm::FunctionType *FTy = 22093d557bc1867b7d7b102f87290194b4be7932c92John McCall CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), 22193d557bc1867b7d7b102f87290194b4be7932c92John McCall FPT->isVariadic()); 22293d557bc1867b7d7b102f87290194b4be7932c92John McCall 2230bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::IntegerType *ptrdiff = getPtrDiffTy(); 224babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1); 22593d557bc1867b7d7b102f87290194b4be7932c92John McCall 226babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); 227babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); 228babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); 229babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall 230d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Extract memptr.adj, which is in the second field. 231d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *RawAdj = Builder.CreateExtractValue(MemFnPtr, 1, "memptr.adj"); 232babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall 233babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall // Compute the true adjustment. 234babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *Adj = RawAdj; 235babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (IsARM) 236babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); 23793d557bc1867b7d7b102f87290194b4be7932c92John McCall 23893d557bc1867b7d7b102f87290194b4be7932c92John McCall // Apply the adjustment and cast back to the original struct type 23993d557bc1867b7d7b102f87290194b4be7932c92John McCall // for consistency. 240babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); 241babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); 242babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); 24393d557bc1867b7d7b102f87290194b4be7932c92John McCall 24493d557bc1867b7d7b102f87290194b4be7932c92John McCall // Load the function pointer. 245d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *FnAsInt = Builder.CreateExtractValue(MemFnPtr, 0, "memptr.ptr"); 24693d557bc1867b7d7b102f87290194b4be7932c92John McCall 24793d557bc1867b7d7b102f87290194b4be7932c92John McCall // If the LSB in the function pointer is 1, the function pointer points to 24893d557bc1867b7d7b102f87290194b4be7932c92John McCall // a virtual function. 249babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *IsVirtual; 250babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (IsARM) 251babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); 252babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall else 253babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); 254babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); 25593d557bc1867b7d7b102f87290194b4be7932c92John McCall Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); 25693d557bc1867b7d7b102f87290194b4be7932c92John McCall 25793d557bc1867b7d7b102f87290194b4be7932c92John McCall // In the virtual path, the adjustment left 'This' pointing to the 25893d557bc1867b7d7b102f87290194b4be7932c92John McCall // vtable of the correct base subobject. The "function pointer" is an 259babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall // offset within the vtable (+1 for the virtual flag on non-ARM). 26093d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnVirtual); 26193d557bc1867b7d7b102f87290194b4be7932c92John McCall 26293d557bc1867b7d7b102f87290194b4be7932c92John McCall // Cast the adjusted this to a pointer to vtable pointer and load. 26393d557bc1867b7d7b102f87290194b4be7932c92John McCall const llvm::Type *VTableTy = Builder.getInt8PtrTy(); 26493d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo()); 265babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall VTable = Builder.CreateLoad(VTable, "memptr.vtable"); 26693d557bc1867b7d7b102f87290194b4be7932c92John McCall 26793d557bc1867b7d7b102f87290194b4be7932c92John McCall // Apply the offset. 268babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *VTableOffset = FnAsInt; 269babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); 270babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall VTable = Builder.CreateGEP(VTable, VTableOffset); 27193d557bc1867b7d7b102f87290194b4be7932c92John McCall 27293d557bc1867b7d7b102f87290194b4be7932c92John McCall // Load the virtual function to call. 27393d557bc1867b7d7b102f87290194b4be7932c92John McCall VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo()); 274babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn"); 27593d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBranch(FnEnd); 27693d557bc1867b7d7b102f87290194b4be7932c92John McCall 27793d557bc1867b7d7b102f87290194b4be7932c92John McCall // In the non-virtual path, the function pointer is actually a 27893d557bc1867b7d7b102f87290194b4be7932c92John McCall // function pointer. 27993d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnNonVirtual); 28093d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *NonVirtualFn = 281babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); 28293d557bc1867b7d7b102f87290194b4be7932c92John McCall 28393d557bc1867b7d7b102f87290194b4be7932c92John McCall // We're done. 28493d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnEnd); 285bbf3bacb3e0c1ebb3e8a4a8b1330404a7e379315Jay Foad llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo(), 2); 28693d557bc1867b7d7b102f87290194b4be7932c92John McCall Callee->addIncoming(VirtualFn, FnVirtual); 28793d557bc1867b7d7b102f87290194b4be7932c92John McCall Callee->addIncoming(NonVirtualFn, FnNonVirtual); 28893d557bc1867b7d7b102f87290194b4be7932c92John McCall return Callee; 28993d557bc1867b7d7b102f87290194b4be7932c92John McCall} 2903023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2916c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall/// Compute an l-value by applying the given pointer-to-member to a 2926c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall/// base object. 2936c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCallllvm::Value *ItaniumCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, 2946c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *Base, 2956c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *MemPtr, 2966c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall const MemberPointerType *MPT) { 2976c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall assert(MemPtr->getType() == getPtrDiffTy()); 2986c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 2996c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall CGBuilderTy &Builder = CGF.Builder; 3006c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3016c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall unsigned AS = cast<llvm::PointerType>(Base->getType())->getAddressSpace(); 3026c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3036c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // Cast to char*. 3046c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall Base = Builder.CreateBitCast(Base, Builder.getInt8Ty()->getPointerTo(AS)); 3056c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3066c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // Apply the offset, which we assume is non-null. 3076c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall llvm::Value *Addr = Builder.CreateInBoundsGEP(Base, MemPtr, "memptr.offset"); 3086c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3096c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // Cast the address to the appropriate pointer type, adopting the 3106c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall // address space of the base pointer. 311eede61a83e90f3cb03ef8665b67d648dccd6ce42Douglas Gregor const llvm::Type *PType 312eede61a83e90f3cb03ef8665b67d648dccd6ce42Douglas Gregor = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); 3136c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall return Builder.CreateBitCast(Addr, PType); 3146c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall} 3156c2ab1d578c6cc1f3ddcc948532cd625f1092ef2John McCall 3163023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall/// Perform a derived-to-base or base-to-derived member pointer conversion. 3170bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3180bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// Obligatory offset/adjustment diagram: 3190bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// <-- offset --> <-- adjustment --> 3200bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// |--------------------------|----------------------|--------------------| 3210bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// ^Derived address point ^Base address point ^Member address point 3220bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3230bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// So when converting a base member pointer to a derived member pointer, 3240bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// we add the offset to the adjustment because the address point has 3250bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// decreased; and conversely, when converting a derived MP to a base MP 3260bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// we subtract the offset from the adjustment because the address point 3270bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// has increased. 3280bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3290bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// The standard forbids (at compile time) conversion to and from 3300bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// virtual bases, which is why we don't have to consider them here. 3310bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// 3320bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// The standard forbids (at run time) casting a derived MP to a base 3330bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// MP when the derived MP does not point to a member of the base. 3340bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// This is why -1 is a reasonable choice for null data member 3350bab0cdab751248ca389a5592bcb70eac5d39260John McCall/// pointers. 336d608cdb7c044365cf4e8764ade1e11e99c176078John McCallllvm::Value * 3370bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, 3380bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E, 3390bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Src) { 3402de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall assert(E->getCastKind() == CK_DerivedToBaseMemberPointer || 3412de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall E->getCastKind() == CK_BaseToDerivedMemberPointer); 3423023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 343d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (isa<llvm::Constant>(Src)) 3440bab0cdab751248ca389a5592bcb70eac5d39260John McCall return EmitMemberPointerConversion(cast<llvm::Constant>(Src), E); 345d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 3463023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall CGBuilderTy &Builder = CGF.Builder; 3473023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3483023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *SrcTy = 3493023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->getSubExpr()->getType()->getAs<MemberPointerType>(); 3503023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>(); 3513023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3523023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 3533023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl(); 3543023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3553023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall bool DerivedToBase = 3562de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall E->getCastKind() == CK_DerivedToBaseMemberPointer; 3573023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 358dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin const CXXRecordDecl *DerivedDecl; 3593023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall if (DerivedToBase) 360dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin DerivedDecl = SrcDecl; 3613023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall else 362dec0984fce504a39a7f085774fb67cfd9957be58Jeffrey Yasskin DerivedDecl = DestDecl; 3633023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 364d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Adj = 365d608cdb7c044365cf4e8764ade1e11e99c176078John McCall CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 366d608cdb7c044365cf4e8764ade1e11e99c176078John McCall E->path_begin(), 367d608cdb7c044365cf4e8764ade1e11e99c176078John McCall E->path_end()); 368d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (!Adj) return Src; 369875ab10245d3bf37252dd822aa1616bb0a391095John McCall 3700bab0cdab751248ca389a5592bcb70eac5d39260John McCall // For member data pointers, this is just a matter of adding the 3710bab0cdab751248ca389a5592bcb70eac5d39260John McCall // offset if the source is non-null. 3720bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (SrcTy->isMemberDataPointer()) { 3730bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Dst; 3740bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (DerivedToBase) 3750bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = Builder.CreateNSWSub(Src, Adj, "adj"); 3760bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 3770bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = Builder.CreateNSWAdd(Src, Adj, "adj"); 3780bab0cdab751248ca389a5592bcb70eac5d39260John McCall 3790bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Null check. 3800bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *Null = llvm::Constant::getAllOnesValue(Src->getType()); 3810bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *IsNull = Builder.CreateICmpEQ(Src, Null, "memptr.isnull"); 3820bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateSelect(IsNull, Src, Dst); 3830bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 3840bab0cdab751248ca389a5592bcb70eac5d39260John McCall 385d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // The this-adjustment is left-shifted by 1 on ARM. 386d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (IsARM) { 387d608cdb7c044365cf4e8764ade1e11e99c176078John McCall uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue(); 388d608cdb7c044365cf4e8764ade1e11e99c176078John McCall Offset <<= 1; 389d608cdb7c044365cf4e8764ade1e11e99c176078John McCall Adj = llvm::ConstantInt::get(Adj->getType(), Offset); 390d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 391d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 392e14add4a275318e7a9cafd3a01f79fb15a5a08bcJohn McCall llvm::Value *SrcAdj = Builder.CreateExtractValue(Src, 1, "src.adj"); 393d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *DstAdj; 394d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (DerivedToBase) 3950bab0cdab751248ca389a5592bcb70eac5d39260John McCall DstAdj = Builder.CreateNSWSub(SrcAdj, Adj, "adj"); 396d608cdb7c044365cf4e8764ade1e11e99c176078John McCall else 3970bab0cdab751248ca389a5592bcb70eac5d39260John McCall DstAdj = Builder.CreateNSWAdd(SrcAdj, Adj, "adj"); 398d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 399e14add4a275318e7a9cafd3a01f79fb15a5a08bcJohn McCall return Builder.CreateInsertValue(Src, DstAdj, 1); 4003023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall} 401cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 402cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallllvm::Constant * 4030bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerConversion(llvm::Constant *C, 4040bab0cdab751248ca389a5592bcb70eac5d39260John McCall const CastExpr *E) { 405cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *SrcTy = 406cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->getSubExpr()->getType()->getAs<MemberPointerType>(); 407cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *DestTy = 408cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->getType()->getAs<MemberPointerType>(); 409cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 410cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool DerivedToBase = 4112de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall E->getCastKind() == CK_DerivedToBaseMemberPointer; 412cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 413cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const CXXRecordDecl *DerivedDecl; 414cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall if (DerivedToBase) 415cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 416cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall else 417cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl(); 418cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 419cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // Calculate the offset to the base class. 420cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Constant *Offset = 421cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 422cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->path_begin(), 423cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->path_end()); 424cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // If there's no offset, we're done. 425cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall if (!Offset) return C; 426cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4270bab0cdab751248ca389a5592bcb70eac5d39260John McCall // If the source is a member data pointer, we have to do a null 4280bab0cdab751248ca389a5592bcb70eac5d39260John McCall // check and then add the offset. In the common case, we can fold 4290bab0cdab751248ca389a5592bcb70eac5d39260John McCall // away the offset. 4300bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (SrcTy->isMemberDataPointer()) { 4310bab0cdab751248ca389a5592bcb70eac5d39260John McCall assert(C->getType() == getPtrDiffTy()); 4320bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4330bab0cdab751248ca389a5592bcb70eac5d39260John McCall // If it's a constant int, just create a new constant int. 4340bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C)) { 4350bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t Src = CI->getSExtValue(); 4360bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4370bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Null converts to null. 4380bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (Src == -1) return CI; 4390bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4400bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Otherwise, just add the offset. 4410bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 4420bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t Dst = (DerivedToBase ? Src - OffsetV : Src + OffsetV); 4430bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::ConstantInt::get(CI->getType(), Dst, /*signed*/ true); 4440bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 4450bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4460bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Otherwise, we have to form a constant select expression. 4470bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *Null = llvm::Constant::getAllOnesValue(C->getType()); 4480bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4490bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *IsNull = 4500bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::ConstantExpr::getICmp(llvm::ICmpInst::ICMP_EQ, C, Null); 4510bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4520bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *Dst; 4530bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (DerivedToBase) 4540bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = llvm::ConstantExpr::getNSWSub(C, Offset); 4550bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 4560bab0cdab751248ca389a5592bcb70eac5d39260John McCall Dst = llvm::ConstantExpr::getNSWAdd(C, Offset); 4570bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4580bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::ConstantExpr::getSelect(IsNull, Null, Dst); 4590bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 4600bab0cdab751248ca389a5592bcb70eac5d39260John McCall 461875ab10245d3bf37252dd822aa1616bb0a391095John McCall // The this-adjustment is left-shifted by 1 on ARM. 462875ab10245d3bf37252dd822aa1616bb0a391095John McCall if (IsARM) { 4630bab0cdab751248ca389a5592bcb70eac5d39260John McCall int64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getSExtValue(); 464875ab10245d3bf37252dd822aa1616bb0a391095John McCall OffsetV <<= 1; 465875ab10245d3bf37252dd822aa1616bb0a391095John McCall Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV); 466875ab10245d3bf37252dd822aa1616bb0a391095John McCall } 467875ab10245d3bf37252dd822aa1616bb0a391095John McCall 468cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C); 469cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4700bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant *Values[2] = { CS->getOperand(0), 0 }; 4710bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (DerivedToBase) 4720bab0cdab751248ca389a5592bcb70eac5d39260John McCall Values[1] = llvm::ConstantExpr::getSub(CS->getOperand(1), Offset); 4730bab0cdab751248ca389a5592bcb70eac5d39260John McCall else 4740bab0cdab751248ca389a5592bcb70eac5d39260John McCall Values[1] = llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset); 4750bab0cdab751248ca389a5592bcb70eac5d39260John McCall 476cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2, 477cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall /*Packed=*/false); 478cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 479cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 480cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 481cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallllvm::Constant * 4820bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) { 4830bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::Type *ptrdiff_t = getPtrDiffTy(); 4840bab0cdab751248ca389a5592bcb70eac5d39260John McCall 4850bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Itanium C++ ABI 2.3: 4860bab0cdab751248ca389a5592bcb70eac5d39260John McCall // A NULL pointer is represented as -1. 4870bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 4880bab0cdab751248ca389a5592bcb70eac5d39260John McCall return llvm::ConstantInt::get(ptrdiff_t, -1ULL, /*isSigned=*/true); 489d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 490d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Zero = llvm::ConstantInt::get(ptrdiff_t, 0); 491d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *Values[2] = { Zero, Zero }; 492d608cdb7c044365cf4e8764ade1e11e99c176078John McCall return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2, 493d608cdb7c044365cf4e8764ade1e11e99c176078John McCall /*Packed=*/false); 494cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 495cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4965808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCallllvm::Constant * 4975808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCallItaniumCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, 4985808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall CharUnits offset) { 4990bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Itanium C++ ABI 2.3: 5000bab0cdab751248ca389a5592bcb70eac5d39260John McCall // A pointer to data member is an offset from the base address of 5010bab0cdab751248ca389a5592bcb70eac5d39260John McCall // the class object containing it, represented as a ptrdiff_t 5025808ce43f8d7e71f5acacc9ca320268c4f37565aJohn McCall return llvm::ConstantInt::get(getPtrDiffTy(), offset.getQuantity()); 5030bab0cdab751248ca389a5592bcb70eac5d39260John McCall} 5040bab0cdab751248ca389a5592bcb70eac5d39260John McCall 505755d8497e39071aa24acc173ff07083e3256b8f8John McCallllvm::Constant *ItaniumCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) { 506d608cdb7c044365cf4e8764ade1e11e99c176078John McCall assert(MD->isInstance() && "Member function must not be static!"); 507d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MD = MD->getCanonicalDecl(); 508875ab10245d3bf37252dd822aa1616bb0a391095John McCall 509d608cdb7c044365cf4e8764ade1e11e99c176078John McCall CodeGenTypes &Types = CGM.getTypes(); 5100bab0cdab751248ca389a5592bcb70eac5d39260John McCall const llvm::Type *ptrdiff_t = getPtrDiffTy(); 511875ab10245d3bf37252dd822aa1616bb0a391095John McCall 512d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Get the function pointer (or index if this is a virtual function). 513d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Constant *MemPtr[2]; 514d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (MD->isVirtual()) { 515d608cdb7c044365cf4e8764ade1e11e99c176078John McCall uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD); 516875ab10245d3bf37252dd822aa1616bb0a391095John McCall 5171246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck const ASTContext &Context = getContext(); 5181246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck CharUnits PointerWidth = 5191246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck Context.toCharUnitsFromBits(Context.Target.getPointerWidth(0)); 5201246ba6f6801390ffc0e1d4b83a2b45e72283b8fKen Dyck uint64_t VTableOffset = (Index * PointerWidth.getQuantity()); 521d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 522d608cdb7c044365cf4e8764ade1e11e99c176078John McCall if (IsARM) { 523d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // ARM C++ ABI 3.2.1: 524d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // This ABI specifies that adj contains twice the this 525d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // adjustment, plus 1 if the member function is virtual. The 526d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // least significant bit of adj then makes exactly the same 527d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // discrimination as the least significant bit of ptr does for 528d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Itanium. 529d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset); 530d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1); 531d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 532d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // Itanium C++ ABI 2.3: 533d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // For a virtual function, [the pointer field] is 1 plus the 534d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // virtual table offset (in bytes) of the function, 535d608cdb7c044365cf4e8764ade1e11e99c176078John McCall // represented as a ptrdiff_t. 536d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1); 537d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 538d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 539d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 540755d8497e39071aa24acc173ff07083e3256b8f8John McCall QualType fnType = MD->getType(); 541755d8497e39071aa24acc173ff07083e3256b8f8John McCall const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); 542755d8497e39071aa24acc173ff07083e3256b8f8John McCall const llvm::Type *Ty; 543755d8497e39071aa24acc173ff07083e3256b8f8John McCall // Check whether the function has a computable LLVM signature. 544755d8497e39071aa24acc173ff07083e3256b8f8John McCall if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) { 545755d8497e39071aa24acc173ff07083e3256b8f8John McCall // The function has a computable LLVM signature; use the correct type. 546755d8497e39071aa24acc173ff07083e3256b8f8John McCall Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), 547755d8497e39071aa24acc173ff07083e3256b8f8John McCall FPT->isVariadic()); 548d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } else { 549755d8497e39071aa24acc173ff07083e3256b8f8John McCall // Use an arbitrary non-function type to tell GetAddrOfFunction that the 550755d8497e39071aa24acc173ff07083e3256b8f8John McCall // function type is incomplete. 551755d8497e39071aa24acc173ff07083e3256b8f8John McCall Ty = ptrdiff_t; 552d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 553755d8497e39071aa24acc173ff07083e3256b8f8John McCall llvm::Constant *addr = CGM.GetAddrOfFunction(MD, Ty); 554d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 555379b5155b4566f63679e1da6b0ceb5fdfa2aec6dJohn McCall MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, ptrdiff_t); 556d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 557d608cdb7c044365cf4e8764ade1e11e99c176078John McCall } 558d608cdb7c044365cf4e8764ade1e11e99c176078John McCall 559d608cdb7c044365cf4e8764ade1e11e99c176078John McCall return llvm::ConstantStruct::get(CGM.getLLVMContext(), 560d608cdb7c044365cf4e8764ade1e11e99c176078John McCall MemPtr, 2, /*Packed=*/false); 561875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 562875ab10245d3bf37252dd822aa1616bb0a391095John McCall 563e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// The comparison algorithm is pretty easy: the member pointers are 564e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// the same if they're either bitwise identical *or* both null. 565e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// 566e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// ARM is different here only because null-ness is more complicated. 567e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 5680bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, 5690bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *L, 5700bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *R, 5710bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT, 5720bab0cdab751248ca389a5592bcb70eac5d39260John McCall bool Inequality) { 573e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 574e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 575e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::ICmpInst::Predicate Eq; 576e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Instruction::BinaryOps And, Or; 577e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (Inequality) { 578e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_NE; 579e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::Or; 580e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::And; 581e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } else { 582e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_EQ; 583e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::And; 584e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::Or; 585e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 586e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 5870bab0cdab751248ca389a5592bcb70eac5d39260John McCall // Member data pointers are easy because there's a unique null 5880bab0cdab751248ca389a5592bcb70eac5d39260John McCall // value, so it just comes down to bitwise equality. 5890bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) 5900bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateICmp(Eq, L, R); 5910bab0cdab751248ca389a5592bcb70eac5d39260John McCall 5920bab0cdab751248ca389a5592bcb70eac5d39260John McCall // For member function pointers, the tautologies are more complex. 5930bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The Itanium tautology is: 594de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L == R) <==> (L.ptr == R.ptr && (L.ptr == 0 || L.adj == R.adj)) 5950bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The ARM tautology is: 596de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L == R) <==> (L.ptr == R.ptr && 597de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L.adj == R.adj || 598de719f7131e1ece5c9d6b5ffe21b83286d29f10fJohn McCall // (L.ptr == 0 && ((L.adj|R.adj) & 1) == 0))) 5990bab0cdab751248ca389a5592bcb70eac5d39260John McCall // The inequality tautologies have exactly the same structure, except 6000bab0cdab751248ca389a5592bcb70eac5d39260John McCall // applying De Morgan's laws. 6010bab0cdab751248ca389a5592bcb70eac5d39260John McCall 6020bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *LPtr = Builder.CreateExtractValue(L, 0, "lhs.memptr.ptr"); 6030bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *RPtr = Builder.CreateExtractValue(R, 0, "rhs.memptr.ptr"); 6040bab0cdab751248ca389a5592bcb70eac5d39260John McCall 605e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.ptr == R.ptr. This must always be 606e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true for equality to hold. 607e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); 608e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 609e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition, together with the assumption that L.ptr == R.ptr, 610e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // tests whether the pointers are both null. ARM imposes an extra 611e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // condition. 612e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); 613e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); 614e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 615e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.adj == R.adj. If this isn't 616e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true, the pointers are unequal unless they're both null. 617d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *LAdj = Builder.CreateExtractValue(L, 1, "lhs.memptr.adj"); 618d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *RAdj = Builder.CreateExtractValue(R, 1, "rhs.memptr.adj"); 619e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); 620e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 621e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Null member function pointers on ARM clear the low bit of Adj, 622e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // so the zero condition has to check that neither low bit is set. 623e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 624e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); 625e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 626e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Compute (l.adj | r.adj) & 1 and test it against zero. 627e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); 628e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); 629e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, 630e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "cmp.or.adj"); 631e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); 632e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 633e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 634e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Tie together all our conditions. 635e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); 636e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Result = Builder.CreateBinOp(And, PtrEq, Result, 637e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Inequality ? "memptr.ne" : "memptr.eq"); 638e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 639e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 640e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 641e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 6420bab0cdab751248ca389a5592bcb70eac5d39260John McCallItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF, 6430bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *MemPtr, 6440bab0cdab751248ca389a5592bcb70eac5d39260John McCall const MemberPointerType *MPT) { 645e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 6460bab0cdab751248ca389a5592bcb70eac5d39260John McCall 6470bab0cdab751248ca389a5592bcb70eac5d39260John McCall /// For member data pointers, this is just a check against -1. 6480bab0cdab751248ca389a5592bcb70eac5d39260John McCall if (MPT->isMemberDataPointer()) { 6490bab0cdab751248ca389a5592bcb70eac5d39260John McCall assert(MemPtr->getType() == getPtrDiffTy()); 6500bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Value *NegativeOne = 6510bab0cdab751248ca389a5592bcb70eac5d39260John McCall llvm::Constant::getAllOnesValue(MemPtr->getType()); 6520bab0cdab751248ca389a5592bcb70eac5d39260John McCall return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool"); 6530bab0cdab751248ca389a5592bcb70eac5d39260John McCall } 654e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 655db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // In Itanium, a member function pointer is not null if 'ptr' is not null. 656d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *Ptr = Builder.CreateExtractValue(MemPtr, 0, "memptr.ptr"); 657e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 658e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); 659e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); 660e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 661db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // On ARM, a member function pointer is also non-null if the low bit of 'adj' 662db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar // (the virtual bit) is set. 663e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 664e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); 665d608cdb7c044365cf4e8764ade1e11e99c176078John McCall llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj"); 666e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); 667db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero, 668db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar "memptr.isvirtual"); 669db27b5fb2d7fc50b8962b2c95e4d43b90c69b1f0Daniel Dunbar Result = Builder.CreateOr(Result, IsVirtual); 670e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 671e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 672e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 673e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 674875ab10245d3bf37252dd822aa1616bb0a391095John McCall 675f16aa103d3afd42fbca2ab346f191bf745cec092John McCall/// The Itanium ABI requires non-zero initialization only for data 676f16aa103d3afd42fbca2ab346f191bf745cec092John McCall/// member pointers, for which '0' is a valid offset. 677f16aa103d3afd42fbca2ab346f191bf745cec092John McCallbool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) { 678f16aa103d3afd42fbca2ab346f191bf745cec092John McCall return MPT->getPointeeType()->isFunctionType(); 679cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 6804c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6814c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The generic ABI passes 'this', plus a VTT if it's initializing a 6824c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// base subobject. 6834c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 6844c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType Type, 6854c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 6864c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 6879cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 6884c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6894c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // 'this' is already there. 6904c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6914c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need to add a VTT parameter (which has type void **). 6924c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0) 6934c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 6944c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 6954c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 6964c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The ARM ABI does the same as the Itanium ABI, but returns 'this'. 6974c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor, 6984c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXCtorType Type, 6994c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 7004c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 7014c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys); 7024c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ResTy = ArgTys[0]; 7034c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7044c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7054c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The generic ABI passes 'this', plus a VTT if it's destroying a 7064c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// base subobject. 7074c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 7084c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType Type, 7094c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 7104c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 7119cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 7124c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7134c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // 'this' is already there. 7144c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7154c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need to add a VTT parameter (which has type void **). 7164c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0) 7174c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy)); 7184c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7194c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7204c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// The ARM ABI does the same as the Itanium ABI, but returns 'this' 7214c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall/// for non-deleting destructors. 7224c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor, 7234c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CXXDtorType Type, 7244c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CanQualType &ResTy, 7254c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall llvm::SmallVectorImpl<CanQualType> &ArgTys) { 7264c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys); 7274c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7284c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (Type != Dtor_Deleting) 7294c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ResTy = ArgTys[0]; 7304c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7314c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7324c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 7334c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 7344c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params) { 7354c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Create the 'this' variable. 7364c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall BuildThisParam(CGF, Params); 7374c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7384c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl()); 7394c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall assert(MD->isInstance()); 7404c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7414c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Check if we need a VTT parameter as well. 7424c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { 7439cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Context = getContext(); 7444c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7454c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // FIXME: avoid the fake decl 7464c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType T = Context.getPointerType(Context.VoidPtrTy); 7474c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ImplicitParamDecl *VTTDecl 7484c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall = ImplicitParamDecl::Create(Context, 0, MD->getLocation(), 7494c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall &Context.Idents.get("vtt"), T); 750d26bc76c98006609002d9930f8840490e88ac5b5John McCall Params.push_back(VTTDecl); 7514c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall getVTTDecl(CGF) = VTTDecl; 7524c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 7534c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7544c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7554c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF, 7564c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall QualType &ResTy, 7574c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall FunctionArgList &Params) { 7584c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params); 7594c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7604c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Return 'this' from certain constructors and destructors. 7614c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (HasThisReturn(CGF.CurGD)) 762d26bc76c98006609002d9930f8840490e88ac5b5John McCall ResTy = Params[0]->getType(); 7634c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7644c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7654c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 7664c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the 'this' slot. 7674c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall EmitThisParam(CGF); 7684c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7694c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the 'vtt' slot if needed. 7704c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (getVTTDecl(CGF)) { 7714c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall getVTTValue(CGF) 7724c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)), 7734c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall "vtt"); 7744c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall } 7754c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7764c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7774c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { 7784c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); 7794c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7804c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// Initialize the return slot to 'this' at the start of the 7814c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall /// function. 7824c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (HasThisReturn(CGF.CurGD)) 7834c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall CGF.Builder.CreateStore(CGF.LoadCXXThis(), CGF.ReturnValue); 7844c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7854c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7864c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCallvoid ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, 7874c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall RValue RV, QualType ResultType) { 7884c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl())) 7894c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType); 7904c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall 7914c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall // Destructor thunks in the ARM ABI have indeterminate results. 7924c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall const llvm::Type *T = 7934c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall cast<llvm::PointerType>(CGF.ReturnValue->getType())->getElementType(); 7944c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall RValue Undef = RValue::get(llvm::UndefValue::get(T)); 7954c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall return ItaniumCXXABI::EmitReturnFromThunk(CGF, Undef, ResultType); 7964c40d98ab7acf5f27fa89b17bd8fc0ef7683df37John McCall} 7971e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 7981e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall/************************** Array allocation cookies **************************/ 7991e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8006ec278d1a354517e20f13a877481453ee7940c78John McCallbool ItaniumCXXABI::NeedsArrayCookie(const CXXNewExpr *expr) { 8016ec278d1a354517e20f13a877481453ee7940c78John McCall // If the class's usual deallocation function takes two arguments, 8026ec278d1a354517e20f13a877481453ee7940c78John McCall // it needs a cookie. 8036ec278d1a354517e20f13a877481453ee7940c78John McCall if (expr->doesUsualArrayDeleteWantSize()) 8046ec278d1a354517e20f13a877481453ee7940c78John McCall return true; 8056ec278d1a354517e20f13a877481453ee7940c78John McCall 8066ec278d1a354517e20f13a877481453ee7940c78John McCall // Otherwise, if the class has a non-trivial destructor, it always 8076ec278d1a354517e20f13a877481453ee7940c78John McCall // needs a cookie. 8086ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXRecordDecl *record = 8096ec278d1a354517e20f13a877481453ee7940c78John McCall expr->getAllocatedType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 8106ec278d1a354517e20f13a877481453ee7940c78John McCall return (record && !record->hasTrivialDestructor()); 8116ec278d1a354517e20f13a877481453ee7940c78John McCall} 8121e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8136ec278d1a354517e20f13a877481453ee7940c78John McCallbool ItaniumCXXABI::NeedsArrayCookie(const CXXDeleteExpr *expr, 8146ec278d1a354517e20f13a877481453ee7940c78John McCall QualType elementType) { 8151e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If the class's usual deallocation function takes two arguments, 8166ec278d1a354517e20f13a877481453ee7940c78John McCall // it needs a cookie. 8176ec278d1a354517e20f13a877481453ee7940c78John McCall if (expr->doesUsualArrayDeleteWantSize()) 8186ec278d1a354517e20f13a877481453ee7940c78John McCall return true; 8196ec278d1a354517e20f13a877481453ee7940c78John McCall 8206ec278d1a354517e20f13a877481453ee7940c78John McCall // Otherwise, if the class has a non-trivial destructor, it always 8216ec278d1a354517e20f13a877481453ee7940c78John McCall // needs a cookie. 8226ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXRecordDecl *record = 8236ec278d1a354517e20f13a877481453ee7940c78John McCall elementType->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); 8246ec278d1a354517e20f13a877481453ee7940c78John McCall return (record && !record->hasTrivialDestructor()); 8251e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8261e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8276ec278d1a354517e20f13a877481453ee7940c78John McCallCharUnits ItaniumCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 8286ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr)) 8291e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CharUnits::Zero(); 8301e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8316ec278d1a354517e20f13a877481453ee7940c78John McCall // Padding is the maximum of sizeof(size_t) and alignof(elementType) 8329cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 8331e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return std::max(Ctx.getTypeSizeInChars(Ctx.getSizeType()), 8346ec278d1a354517e20f13a877481453ee7940c78John McCall Ctx.getTypeAlignInChars(expr->getAllocatedType())); 8351e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8361e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8371e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallllvm::Value *ItaniumCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 8381e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 8391e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 8406ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 8411e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType) { 8426ec278d1a354517e20f13a877481453ee7940c78John McCall assert(NeedsArrayCookie(expr)); 8431e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8441e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 8451e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8469cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 8471e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType SizeTy = Ctx.getSizeType(); 8481e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits SizeSize = Ctx.getTypeSizeInChars(SizeTy); 8491e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8501e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The size of the cookie. 8511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieSize = 8521e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall std::max(SizeSize, Ctx.getTypeAlignInChars(ElementType)); 8531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Compute an offset to the cookie. 8551e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *CookiePtr = NewPtr; 8561e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieOffset = CookieSize - SizeSize; 8571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall if (!CookieOffset.isZero()) 8581e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_64(CookiePtr, 8591e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieOffset.getQuantity()); 8601e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8611e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Write the number of elements into the appropriate slot. 8621e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr 8631e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall = CGF.Builder.CreateBitCast(CookiePtr, 8641e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.ConvertType(SizeTy)->getPointerTo(AS)); 8651e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(NumElements, NumElementsPtr); 8661e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8671e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Finally, compute a pointer to the actual data buffer by skipping 8681e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // over the cookie completely. 8691e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 8701e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize.getQuantity()); 8711e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 8721e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8731e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallvoid ItaniumCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 8741e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *Ptr, 8756ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 8761e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, 8771e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&NumElements, 8781e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, 8791e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits &CookieSize) { 8801e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Derive a char* in the same address space as the pointer. 8811e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 8821e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 8831e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8841e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If we don't need an array cookie, bail out early. 8856ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr, ElementType)) { 8861e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 8871e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = 0; 8881e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = CharUnits::Zero(); 8891e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return; 8901e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall } 8911e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8929cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType SizeTy = getContext().getSizeType(); 8939cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 8941e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 8951e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8961e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize 8979cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall = std::max(SizeSize, getContext().getTypeAlignInChars(ElementType)); 8981e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 8991e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits NumElementsOffset = CookieSize - SizeSize; 9001e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9011e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Compute the allocated pointer. 9021e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 9031e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 9041e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall -CookieSize.getQuantity()); 9051e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9061e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr = AllocPtr; 9071e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall if (!NumElementsOffset.isZero()) 9081e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 9091e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateConstInBoundsGEP1_64(NumElementsPtr, 9101e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsOffset.getQuantity()); 9111e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 9121e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 9131e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 9141e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9151e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9166ec278d1a354517e20f13a877481453ee7940c78John McCallCharUnits ARMCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) { 9176ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr)) 9181e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CharUnits::Zero(); 9191e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9201e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // On ARM, the cookie is always: 9211e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // struct array_cookie { 9221e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // std::size_t element_size; // element_size != 0 9231e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // std::size_t element_count; 9241e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // }; 9251e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // TODO: what should we do if the allocated type actually wants 9261e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // greater alignment? 9271e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return getContext().getTypeSizeInChars(getContext().getSizeType()) * 2; 9281e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9291e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9301e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallllvm::Value *ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, 9311e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NewPtr, 9321e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElements, 9336ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXNewExpr *expr, 9341e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType) { 9356ec278d1a354517e20f13a877481453ee7940c78John McCall assert(NeedsArrayCookie(expr)); 9361e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9371e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // NewPtr is a char*. 9381e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9391e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(NewPtr->getType())->getAddressSpace(); 9401e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9419cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall ASTContext &Ctx = getContext(); 9421e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits SizeSize = Ctx.getTypeSizeInChars(Ctx.getSizeType()); 9431e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::IntegerType *SizeTy = 9441e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall cast<llvm::IntegerType>(CGF.ConvertType(Ctx.getSizeType())); 9451e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9461e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The cookie is always at the start of the buffer. 9471e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *CookiePtr = NewPtr; 9481e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9491e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The first element is the element size. 9501e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateBitCast(CookiePtr, SizeTy->getPointerTo(AS)); 9511e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *ElementSize = llvm::ConstantInt::get(SizeTy, 9521e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall Ctx.getTypeSizeInChars(ElementType).getQuantity()); 9531e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(ElementSize, CookiePtr); 9541e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9551e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The second element is the element count. 9561e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookiePtr = CGF.Builder.CreateConstInBoundsGEP1_32(CookiePtr, 1); 9571e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateStore(NumElements, CookiePtr); 9581e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9591e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Finally, compute a pointer to the actual data buffer by skipping 9601e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // over the cookie completely. 9611e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits CookieSize = 2 * SizeSize; 9621e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return CGF.Builder.CreateConstInBoundsGEP1_64(NewPtr, 9631e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize.getQuantity()); 9641e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 9651e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9661e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCallvoid ARMCXXABI::ReadArrayCookie(CodeGenFunction &CGF, 9671e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *Ptr, 9686ec278d1a354517e20f13a877481453ee7940c78John McCall const CXXDeleteExpr *expr, 9691e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall QualType ElementType, 9701e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&NumElements, 9711e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *&AllocPtr, 9721e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CharUnits &CookieSize) { 9731e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // Derive a char* in the same address space as the pointer. 9741e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall unsigned AS = cast<llvm::PointerType>(Ptr->getType())->getAddressSpace(); 9751e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *CharPtrTy = CGF.Builder.getInt8Ty()->getPointerTo(AS); 9761e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9771e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // If we don't need an array cookie, bail out early. 9786ec278d1a354517e20f13a877481453ee7940c78John McCall if (!NeedsArrayCookie(expr, ElementType)) { 9791e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 9801e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = 0; 9811e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = CharUnits::Zero(); 9821e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall return; 9831e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall } 9841e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9859cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall QualType SizeTy = getContext().getSizeType(); 9869cb2cee212d708220c52249ceac4cdd9f2b8aeb0John McCall CharUnits SizeSize = getContext().getTypeSizeInChars(SizeTy); 9871e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 9881e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9891e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The cookie size is always 2 * sizeof(size_t). 9901e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CookieSize = 2 * SizeSize; 9911e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9921e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The allocated pointer is the input ptr, minus that amount. 9931e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateBitCast(Ptr, CharPtrTy); 9941e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall AllocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 9951e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall -CookieSize.getQuantity()); 9961e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 9971e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall // The number of elements is at offset sizeof(size_t) relative to that. 9981e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall llvm::Value *NumElementsPtr 9991e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall = CGF.Builder.CreateConstInBoundsGEP1_64(AllocPtr, 10001e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall SizeSize.getQuantity()); 10011e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElementsPtr = 10021e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo(AS)); 10031e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 10041e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall} 10051e7fe751466ea82665fd21e9162fd7cc9c5f412dJohn McCall 10065cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/*********************** Static local initialization **************************/ 10075cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10085cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardAcquireFn(CodeGenModule &CGM, 10095cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::PointerType *GuardPtrTy) { 10105cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // int __cxa_guard_acquire(__guard *guard_object); 10115cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10125cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall std::vector<const llvm::Type*> Args(1, GuardPtrTy); 10135cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::FunctionType *FTy = 10145cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy), 10155cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Args, /*isVarArg=*/false); 10165cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10175cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_acquire"); 10185cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10195cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10205cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardReleaseFn(CodeGenModule &CGM, 10215cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::PointerType *GuardPtrTy) { 10225cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // void __cxa_guard_release(__guard *guard_object); 10235cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10245cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall std::vector<const llvm::Type*> Args(1, GuardPtrTy); 10255cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10265cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::FunctionType *FTy = 10275cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 10285cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Args, /*isVarArg=*/false); 10295cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10305cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_release"); 10315cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10325cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10335cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallstatic llvm::Constant *getGuardAbortFn(CodeGenModule &CGM, 10345cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::PointerType *GuardPtrTy) { 10355cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // void __cxa_guard_abort(__guard *guard_object); 10365cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10375cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall std::vector<const llvm::Type*> Args(1, GuardPtrTy); 10385cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10395cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::FunctionType *FTy = 10405cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()), 10415cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Args, /*isVarArg=*/false); 10425cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10435cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_guard_abort"); 10445cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10455cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10465cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCallnamespace { 10475cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall struct CallGuardAbort : EHScopeStack::Cleanup { 10485cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::GlobalVariable *Guard; 10495cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {} 10505cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10515cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall void Emit(CodeGenFunction &CGF, bool IsForEH) { 10525cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.Builder.CreateCall(getGuardAbortFn(CGF.CGM, Guard->getType()), Guard) 10535cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall ->setDoesNotThrow(); 10545cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 10555cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall }; 10565cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 10575cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10585cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// The ARM code here follows the Itanium code closely enough that we 10595cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall/// just special-case it at particular places. 10603030eb82593097502469a8b3fc26112c79c75605John McCallvoid ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, 10613030eb82593097502469a8b3fc26112c79c75605John McCall const VarDecl &D, 10623030eb82593097502469a8b3fc26112c79c75605John McCall llvm::GlobalVariable *GV) { 10635cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGBuilderTy &Builder = CGF.Builder; 10643030eb82593097502469a8b3fc26112c79c75605John McCall 10653030eb82593097502469a8b3fc26112c79c75605John McCall // We only need to use thread-safe statics for local variables; 10663030eb82593097502469a8b3fc26112c79c75605John McCall // global initialization is always single-threaded. 10673030eb82593097502469a8b3fc26112c79c75605John McCall bool ThreadsafeStatics = (getContext().getLangOptions().ThreadsafeStatics && 10683030eb82593097502469a8b3fc26112c79c75605John McCall D.isLocalVarDecl()); 1069173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson 1070173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson const llvm::IntegerType *GuardTy; 1071173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson 1072173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // If we have a global variable with internal linkage and thread-safe statics 1073173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // are disabled, we can just let the guard variable be of type i8. 1074173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson bool UseInt8GuardVariable = !ThreadsafeStatics && GV->hasInternalLinkage(); 1075173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson if (UseInt8GuardVariable) 1076173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson GuardTy = Builder.getInt8Ty(); 1077173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson else { 1078173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson // Guard variables are 64 bits in the generic ABI and 32 bits on ARM. 1079173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson GuardTy = (IsARM ? Builder.getInt32Ty() : Builder.getInt64Ty()); 1080173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson } 10815cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::PointerType *GuardPtrTy = GuardTy->getPointerTo(); 10825cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10835cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Create the guard variable. 10845cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::SmallString<256> GuardVName; 1085f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola llvm::raw_svector_ostream Out(GuardVName); 1086f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola getMangleContext().mangleItaniumGuardVariable(&D, Out); 1087f0be979bddb8baa28e77693a3dc931e487b2a9f2Rafael Espindola Out.flush(); 1088112c967bd5c862a0f5d7913aa06700c048807db8John McCall 10893030eb82593097502469a8b3fc26112c79c75605John McCall // Just absorb linkage and visibility from the variable. 10905cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::GlobalVariable *GuardVariable = 10915cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall new llvm::GlobalVariable(CGM.getModule(), GuardTy, 10923030eb82593097502469a8b3fc26112c79c75605John McCall false, GV->getLinkage(), 10935cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::ConstantInt::get(GuardTy, 0), 10945cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall GuardVName.str()); 1095112c967bd5c862a0f5d7913aa06700c048807db8John McCall GuardVariable->setVisibility(GV->getVisibility()); 10965cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 10975cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Test whether the variable has completed initialization. 10985cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *IsInitialized; 10995cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11005cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ARM C++ ABI 3.2.3.1: 11015cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // To support the potential use of initialization guard variables 11025cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // as semaphores that are the target of ARM SWP and LDREX/STREX 11035cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // synchronizing instructions we define a static initialization 11045cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // guard variable to be a 4-byte aligned, 4- byte word with the 11055cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // following inline access protocol. 11065cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // #define INITIALIZED 1 11075cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if ((obj_guard & INITIALIZED) != INITIALIZED) { 11085cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if (__cxa_guard_acquire(&obj_guard)) 11095cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... 11105cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 1111173d51286bcaff4b6b76eebf6542d3b1311142e2Anders Carlsson if (IsARM && !UseInt8GuardVariable) { 11125cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V = Builder.CreateLoad(GuardVariable); 11135cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall V = Builder.CreateAnd(V, Builder.getInt32(1)); 11145cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 11155cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11165cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Itanium C++ ABI 3.3.2: 11175cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // The following is pseudo-code showing how these functions can be used: 11185cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if (obj_guard.first_byte == 0) { 11195cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // if ( __cxa_guard_acquire (&obj_guard) ) { 11205cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // try { 11215cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... initialize the object ...; 11225cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } catch (...) { 11235cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // __cxa_guard_abort (&obj_guard); 11245cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // throw; 11255cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 11265cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // ... queue object destructor with __cxa_atexit() ...; 11275cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // __cxa_guard_release (&obj_guard); 11285cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 11295cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // } 11305cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } else { 11315cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Load the first byte of the guard variable. 11325cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall const llvm::Type *PtrTy = Builder.getInt8PtrTy(); 11335cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V = 11345cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateLoad(Builder.CreateBitCast(GuardVariable, PtrTy), "tmp"); 11355cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11365cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall IsInitialized = Builder.CreateIsNull(V, "guard.uninitialized"); 11375cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11385cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11395cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *InitCheckBlock = CGF.createBasicBlock("init.check"); 11405cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *EndBlock = CGF.createBasicBlock("init.end"); 11415cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11425cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Check if the first byte of the guard variable is zero. 11435cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateCondBr(IsInitialized, InitCheckBlock, EndBlock); 11445cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11455cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(InitCheckBlock); 11465cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11475cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Variables used when coping with thread-safe statics and exceptions. 11485cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall if (ThreadsafeStatics) { 11495cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_acquire. 11505cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::Value *V 11515cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall = Builder.CreateCall(getGuardAcquireFn(CGM, GuardPtrTy), GuardVariable); 11525cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11535cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init"); 11545cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11555cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), 11565cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall InitBlock, EndBlock); 11575cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11585cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_abort along the exceptional edge. 11595cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, GuardVariable); 11605cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11615cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(InitBlock); 11625cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11635cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11645cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Emit the initializer and add a global destructor if appropriate. 11655cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitCXXGlobalVarDeclInit(D, GV); 11665cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11675cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall if (ThreadsafeStatics) { 11685cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Pop the guard-abort cleanup if we pushed one. 11695cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.PopCleanupBlock(); 11705cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11715cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall // Call __cxa_guard_release. This cannot throw. 11725cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateCall(getGuardReleaseFn(CGM, GuardPtrTy), GuardVariable); 11735cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } else { 11745cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall Builder.CreateStore(llvm::ConstantInt::get(GuardTy, 1), GuardVariable); 11755cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall } 11765cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall 11775cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall CGF.EmitBlock(EndBlock); 11785cd91b513455fd7753e8815b54f0a49bbca6602dJohn McCall} 1179