ItaniumCXXABI.cpp revision e9fd7eb6c67676dc27e84eac429aec4f3be51f26
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// 103a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis// This provides C++ code generation targetting 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" 2293d557bc1867b7d7b102f87290194b4be7932c92John McCall#include "CodeGenFunction.h" 233a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis#include "CodeGenModule.h" 243a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis#include "Mangle.h" 2593d557bc1867b7d7b102f87290194b4be7932c92John McCall#include <clang/AST/Type.h> 2693d557bc1867b7d7b102f87290194b4be7932c92John McCall#include <llvm/Value.h> 273a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 283a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davisusing namespace clang; 2993d557bc1867b7d7b102f87290194b4be7932c92John McCallusing namespace CodeGen; 303a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 313a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davisnamespace { 32071cc7deffad608165b1ddd5263e8bf181861520Charles Davisclass ItaniumCXXABI : public CodeGen::CGCXXABI { 3393d557bc1867b7d7b102f87290194b4be7932c92John McCallprotected: 3493d557bc1867b7d7b102f87290194b4be7932c92John McCall CodeGenModule &CGM; 353a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis CodeGen::MangleContext MangleCtx; 36babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall bool IsARM; 373a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davispublic: 38babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool IsARM = false) : 39babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall CGM(CGM), MangleCtx(CGM.getContext(), CGM.getDiags()), IsARM(IsARM) { } 403a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 413a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis CodeGen::MangleContext &getMangleContext() { 423a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis return MangleCtx; 433a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis } 4493d557bc1867b7d7b102f87290194b4be7932c92John McCall 45cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool RequiresNonZeroInitializer(QualType T); 46cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool RequiresNonZeroInitializer(const CXXRecordDecl *D); 47cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 4893d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 4993d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *&This, 5093d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *MemFnPtr, 5193d557bc1867b7d7b102f87290194b4be7932c92John McCall const MemberPointerType *MPT); 523023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 53cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall void EmitMemberFunctionPointerConversion(CodeGenFunction &CGF, 54cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const CastExpr *E, 55cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Src, 56cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Dest, 57cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool VolatileDest); 58cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 59cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Constant *EmitMemberFunctionPointerConversion(llvm::Constant *C, 60cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const CastExpr *E); 61cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 62cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall void EmitNullMemberFunctionPointer(CodeGenFunction &CGF, 63cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *MPT, 64cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Dest, 65cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool VolatileDest); 66cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 67cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Constant *EmitNullMemberFunctionPointer(const MemberPointerType *MPT); 68cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 69875ab10245d3bf37252dd822aa1616bb0a391095John McCall void EmitMemberFunctionPointer(CodeGenFunction &CGF, 70875ab10245d3bf37252dd822aa1616bb0a391095John McCall const CXXMethodDecl *MD, 71875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Value *Dest, 72875ab10245d3bf37252dd822aa1616bb0a391095John McCall bool VolatileDest); 73875ab10245d3bf37252dd822aa1616bb0a391095John McCall 74875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Constant *EmitMemberFunctionPointer(const CXXMethodDecl *MD); 75875ab10245d3bf37252dd822aa1616bb0a391095John McCall 76e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *EmitMemberFunctionPointerComparison(CodeGenFunction &CGF, 77e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *L, 78e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *R, 79e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall const MemberPointerType *MPT, 80e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall bool Inequality); 81e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 82e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF, 83e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Addr, 84e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall const MemberPointerType *MPT); 85e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 86875ab10245d3bf37252dd822aa1616bb0a391095John McCallprivate: 87875ab10245d3bf37252dd822aa1616bb0a391095John McCall void GetMemberFunctionPointer(const CXXMethodDecl *MD, 88875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Constant *(&Array)[2]); 893a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis}; 90ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall 91ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallclass ARMCXXABI : public ItaniumCXXABI { 92ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallpublic: 93babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} 94ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall}; 953a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis} 963a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 97071cc7deffad608165b1ddd5263e8bf181861520Charles DavisCodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) { 983a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis return new ItaniumCXXABI(CGM); 993a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis} 1003a811f1f4286ee3fd0c563c1cfe623956f3caa24Charles Davis 101ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCallCodeGen::CGCXXABI *CodeGen::CreateARMCXXABI(CodeGenModule &CGM) { 102ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall return new ARMCXXABI(CGM); 103ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall} 104ee79a4c30e5d1c5285551c9a25b8ec6d45d46aa7John McCall 105875ab10245d3bf37252dd822aa1616bb0a391095John McCallvoid ItaniumCXXABI::GetMemberFunctionPointer(const CXXMethodDecl *MD, 106875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Constant *(&MemPtr)[2]) { 107875ab10245d3bf37252dd822aa1616bb0a391095John McCall assert(MD->isInstance() && "Member function must not be static!"); 108875ab10245d3bf37252dd822aa1616bb0a391095John McCall 109875ab10245d3bf37252dd822aa1616bb0a391095John McCall MD = MD->getCanonicalDecl(); 110875ab10245d3bf37252dd822aa1616bb0a391095John McCall 111875ab10245d3bf37252dd822aa1616bb0a391095John McCall CodeGenTypes &Types = CGM.getTypes(); 112875ab10245d3bf37252dd822aa1616bb0a391095John McCall const llvm::Type *ptrdiff_t = 113875ab10245d3bf37252dd822aa1616bb0a391095John McCall Types.ConvertType(CGM.getContext().getPointerDiffType()); 114875ab10245d3bf37252dd822aa1616bb0a391095John McCall 115875ab10245d3bf37252dd822aa1616bb0a391095John McCall // Get the function pointer (or index if this is a virtual function). 116875ab10245d3bf37252dd822aa1616bb0a391095John McCall if (MD->isVirtual()) { 117875ab10245d3bf37252dd822aa1616bb0a391095John McCall uint64_t Index = CGM.getVTables().getMethodVTableIndex(MD); 118875ab10245d3bf37252dd822aa1616bb0a391095John McCall 119875ab10245d3bf37252dd822aa1616bb0a391095John McCall // FIXME: We shouldn't use / 8 here. 120875ab10245d3bf37252dd822aa1616bb0a391095John McCall uint64_t PointerWidthInBytes = 121875ab10245d3bf37252dd822aa1616bb0a391095John McCall CGM.getContext().Target.getPointerWidth(0) / 8; 122875ab10245d3bf37252dd822aa1616bb0a391095John McCall uint64_t VTableOffset = (Index * PointerWidthInBytes); 123875ab10245d3bf37252dd822aa1616bb0a391095John McCall 124875ab10245d3bf37252dd822aa1616bb0a391095John McCall if (IsARM) { 125875ab10245d3bf37252dd822aa1616bb0a391095John McCall // ARM C++ ABI 3.2.1: 126875ab10245d3bf37252dd822aa1616bb0a391095John McCall // This ABI specifies that adj contains twice the this 127875ab10245d3bf37252dd822aa1616bb0a391095John McCall // adjustment, plus 1 if the member function is virtual. The 128875ab10245d3bf37252dd822aa1616bb0a391095John McCall // least significant bit of adj then makes exactly the same 129875ab10245d3bf37252dd822aa1616bb0a391095John McCall // discrimination as the least significant bit of ptr does for 130875ab10245d3bf37252dd822aa1616bb0a391095John McCall // Itanium. 131875ab10245d3bf37252dd822aa1616bb0a391095John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset); 132875ab10245d3bf37252dd822aa1616bb0a391095John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 1); 133875ab10245d3bf37252dd822aa1616bb0a391095John McCall } else { 134875ab10245d3bf37252dd822aa1616bb0a391095John McCall // Itanium C++ ABI 2.3: 135875ab10245d3bf37252dd822aa1616bb0a391095John McCall // For a virtual function, [the pointer field] is 1 plus the 136875ab10245d3bf37252dd822aa1616bb0a391095John McCall // virtual table offset (in bytes) of the function, 137875ab10245d3bf37252dd822aa1616bb0a391095John McCall // represented as a ptrdiff_t. 138875ab10245d3bf37252dd822aa1616bb0a391095John McCall MemPtr[0] = llvm::ConstantInt::get(ptrdiff_t, VTableOffset + 1); 139875ab10245d3bf37252dd822aa1616bb0a391095John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 140875ab10245d3bf37252dd822aa1616bb0a391095John McCall } 141875ab10245d3bf37252dd822aa1616bb0a391095John McCall } else { 142875ab10245d3bf37252dd822aa1616bb0a391095John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 143875ab10245d3bf37252dd822aa1616bb0a391095John McCall const llvm::Type *Ty; 144875ab10245d3bf37252dd822aa1616bb0a391095John McCall // Check whether the function has a computable LLVM signature. 145875ab10245d3bf37252dd822aa1616bb0a391095John McCall if (!CodeGenTypes::VerifyFuncTypeComplete(FPT)) { 146875ab10245d3bf37252dd822aa1616bb0a391095John McCall // The function has a computable LLVM signature; use the correct type. 147875ab10245d3bf37252dd822aa1616bb0a391095John McCall Ty = Types.GetFunctionType(Types.getFunctionInfo(MD), FPT->isVariadic()); 148875ab10245d3bf37252dd822aa1616bb0a391095John McCall } else { 149875ab10245d3bf37252dd822aa1616bb0a391095John McCall // Use an arbitrary non-function type to tell GetAddrOfFunction that the 150875ab10245d3bf37252dd822aa1616bb0a391095John McCall // function type is incomplete. 151875ab10245d3bf37252dd822aa1616bb0a391095John McCall Ty = ptrdiff_t; 152875ab10245d3bf37252dd822aa1616bb0a391095John McCall } 153875ab10245d3bf37252dd822aa1616bb0a391095John McCall 154875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Constant *Addr = CGM.GetAddrOfFunction(MD, Ty); 155875ab10245d3bf37252dd822aa1616bb0a391095John McCall MemPtr[0] = llvm::ConstantExpr::getPtrToInt(Addr, ptrdiff_t); 156875ab10245d3bf37252dd822aa1616bb0a391095John McCall MemPtr[1] = llvm::ConstantInt::get(ptrdiff_t, 0); 157875ab10245d3bf37252dd822aa1616bb0a391095John McCall } 158875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 159875ab10245d3bf37252dd822aa1616bb0a391095John McCall 160875ab10245d3bf37252dd822aa1616bb0a391095John McCall 161babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the Itanium and ARM ABIs, method pointers have the form: 162babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// struct { ptrdiff_t ptr; ptrdiff_t adj; } memptr; 163babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 164babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the Itanium ABI: 165babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - method pointers are virtual if (memptr.ptr & 1) is nonzero 166babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the this-adjustment is (memptr.adj) 167babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the virtual offset is (memptr.ptr - 1) 168babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 169babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// In the ARM ABI: 170babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - method pointers are virtual if (memptr.adj & 1) is nonzero 171babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the this-adjustment is (memptr.adj >> 1) 172babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// - the virtual offset is (memptr.ptr) 173babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// ARM uses 'adj' for the virtual flag because Thumb functions 174babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// may be only single-byte aligned. 175babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 176babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// If the member is virtual, the adjusted 'this' pointer points 177babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// to a vtable pointer from which the virtual offset is applied. 178babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// 179babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// If the member is non-virtual, memptr.ptr is the address of 180babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall/// the function to call. 18193d557bc1867b7d7b102f87290194b4be7932c92John McCallllvm::Value * 18293d557bc1867b7d7b102f87290194b4be7932c92John McCallItaniumCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, 18393d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *&This, 18493d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *MemFnPtr, 18593d557bc1867b7d7b102f87290194b4be7932c92John McCall const MemberPointerType *MPT) { 18693d557bc1867b7d7b102f87290194b4be7932c92John McCall CGBuilderTy &Builder = CGF.Builder; 18793d557bc1867b7d7b102f87290194b4be7932c92John McCall 18893d557bc1867b7d7b102f87290194b4be7932c92John McCall const FunctionProtoType *FPT = 18993d557bc1867b7d7b102f87290194b4be7932c92John McCall MPT->getPointeeType()->getAs<FunctionProtoType>(); 19093d557bc1867b7d7b102f87290194b4be7932c92John McCall const CXXRecordDecl *RD = 19193d557bc1867b7d7b102f87290194b4be7932c92John McCall cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 19293d557bc1867b7d7b102f87290194b4be7932c92John McCall 19393d557bc1867b7d7b102f87290194b4be7932c92John McCall const llvm::FunctionType *FTy = 19493d557bc1867b7d7b102f87290194b4be7932c92John McCall CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), 19593d557bc1867b7d7b102f87290194b4be7932c92John McCall FPT->isVariadic()); 19693d557bc1867b7d7b102f87290194b4be7932c92John McCall 197babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall const llvm::IntegerType *ptrdiff = CGF.IntPtrTy; 198babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Constant *ptrdiff_1 = llvm::ConstantInt::get(ptrdiff, 1); 19993d557bc1867b7d7b102f87290194b4be7932c92John McCall 200babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnVirtual = CGF.createBasicBlock("memptr.virtual"); 201babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnNonVirtual = CGF.createBasicBlock("memptr.nonvirtual"); 202babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::BasicBlock *FnEnd = CGF.createBasicBlock("memptr.end"); 203babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall 204babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall // Load memptr.adj, which is in the second field. 205babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *RawAdj = Builder.CreateStructGEP(MemFnPtr, 1); 206babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall RawAdj = Builder.CreateLoad(RawAdj, "memptr.adj"); 207babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall 208babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall // Compute the true adjustment. 209babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *Adj = RawAdj; 210babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (IsARM) 211babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Adj = Builder.CreateAShr(Adj, ptrdiff_1, "memptr.adj.shifted"); 21293d557bc1867b7d7b102f87290194b4be7932c92John McCall 21393d557bc1867b7d7b102f87290194b4be7932c92John McCall // Apply the adjustment and cast back to the original struct type 21493d557bc1867b7d7b102f87290194b4be7932c92John McCall // for consistency. 215babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *Ptr = Builder.CreateBitCast(This, Builder.getInt8PtrTy()); 216babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Ptr = Builder.CreateInBoundsGEP(Ptr, Adj); 217babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall This = Builder.CreateBitCast(Ptr, This->getType(), "this.adjusted"); 21893d557bc1867b7d7b102f87290194b4be7932c92John McCall 21993d557bc1867b7d7b102f87290194b4be7932c92John McCall // Load the function pointer. 220babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0); 221babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "memptr.ptr"); 22293d557bc1867b7d7b102f87290194b4be7932c92John McCall 22393d557bc1867b7d7b102f87290194b4be7932c92John McCall // If the LSB in the function pointer is 1, the function pointer points to 22493d557bc1867b7d7b102f87290194b4be7932c92John McCall // a virtual function. 225babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *IsVirtual; 226babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (IsARM) 227babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateAnd(RawAdj, ptrdiff_1); 228babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall else 229babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateAnd(FnAsInt, ptrdiff_1); 230babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall IsVirtual = Builder.CreateIsNotNull(IsVirtual, "memptr.isvirtual"); 23193d557bc1867b7d7b102f87290194b4be7932c92John McCall Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); 23293d557bc1867b7d7b102f87290194b4be7932c92John McCall 23393d557bc1867b7d7b102f87290194b4be7932c92John McCall // In the virtual path, the adjustment left 'This' pointing to the 23493d557bc1867b7d7b102f87290194b4be7932c92John McCall // vtable of the correct base subobject. The "function pointer" is an 235babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall // offset within the vtable (+1 for the virtual flag on non-ARM). 23693d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnVirtual); 23793d557bc1867b7d7b102f87290194b4be7932c92John McCall 23893d557bc1867b7d7b102f87290194b4be7932c92John McCall // Cast the adjusted this to a pointer to vtable pointer and load. 23993d557bc1867b7d7b102f87290194b4be7932c92John McCall const llvm::Type *VTableTy = Builder.getInt8PtrTy(); 24093d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy->getPointerTo()); 241babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall VTable = Builder.CreateLoad(VTable, "memptr.vtable"); 24293d557bc1867b7d7b102f87290194b4be7932c92John McCall 24393d557bc1867b7d7b102f87290194b4be7932c92John McCall // Apply the offset. 244babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *VTableOffset = FnAsInt; 245babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall if (!IsARM) VTableOffset = Builder.CreateSub(VTableOffset, ptrdiff_1); 246babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall VTable = Builder.CreateGEP(VTable, VTableOffset); 24793d557bc1867b7d7b102f87290194b4be7932c92John McCall 24893d557bc1867b7d7b102f87290194b4be7932c92John McCall // Load the virtual function to call. 24993d557bc1867b7d7b102f87290194b4be7932c92John McCall VTable = Builder.CreateBitCast(VTable, FTy->getPointerTo()->getPointerTo()); 250babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "memptr.virtualfn"); 25193d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBranch(FnEnd); 25293d557bc1867b7d7b102f87290194b4be7932c92John McCall 25393d557bc1867b7d7b102f87290194b4be7932c92John McCall // In the non-virtual path, the function pointer is actually a 25493d557bc1867b7d7b102f87290194b4be7932c92John McCall // function pointer. 25593d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnNonVirtual); 25693d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::Value *NonVirtualFn = 257babc9a9ecc3fbc04edaac5a1f4fb3e869815b25cJohn McCall Builder.CreateIntToPtr(FnAsInt, FTy->getPointerTo(), "memptr.nonvirtualfn"); 25893d557bc1867b7d7b102f87290194b4be7932c92John McCall 25993d557bc1867b7d7b102f87290194b4be7932c92John McCall // We're done. 26093d557bc1867b7d7b102f87290194b4be7932c92John McCall CGF.EmitBlock(FnEnd); 26193d557bc1867b7d7b102f87290194b4be7932c92John McCall llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo()); 26293d557bc1867b7d7b102f87290194b4be7932c92John McCall Callee->reserveOperandSpace(2); 26393d557bc1867b7d7b102f87290194b4be7932c92John McCall Callee->addIncoming(VirtualFn, FnVirtual); 26493d557bc1867b7d7b102f87290194b4be7932c92John McCall Callee->addIncoming(NonVirtualFn, FnNonVirtual); 26593d557bc1867b7d7b102f87290194b4be7932c92John McCall return Callee; 26693d557bc1867b7d7b102f87290194b4be7932c92John McCall} 2673023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2683023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall/// Perform a derived-to-base or base-to-derived member pointer conversion. 269cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallvoid ItaniumCXXABI::EmitMemberFunctionPointerConversion(CodeGenFunction &CGF, 270cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const CastExpr *E, 271cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Src, 272cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Dest, 273cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool VolatileDest) { 2743023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall assert(E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer || 2753023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->getCastKind() == CastExpr::CK_BaseToDerivedMemberPointer); 2763023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2773023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall CGBuilderTy &Builder = CGF.Builder; 2783023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2793023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *SrcTy = 2803023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->getSubExpr()->getType()->getAs<MemberPointerType>(); 2813023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const MemberPointerType *DestTy = E->getType()->getAs<MemberPointerType>(); 2823023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2833023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *SrcDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 2843023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *DestDecl = DestTy->getClass()->getAsCXXRecordDecl(); 2853023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2863023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall llvm::Value *SrcPtr = Builder.CreateStructGEP(Src, 0, "src.ptr"); 2873023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall SrcPtr = Builder.CreateLoad(SrcPtr); 2883023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2893023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall llvm::Value *SrcAdj = Builder.CreateStructGEP(Src, 1, "src.adj"); 2903023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall SrcAdj = Builder.CreateLoad(SrcAdj); 2913023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2923023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall llvm::Value *DstPtr = Builder.CreateStructGEP(Dest, 0, "dst.ptr"); 2933023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall Builder.CreateStore(SrcPtr, DstPtr, VolatileDest); 2943023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2953023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall llvm::Value *DstAdj = Builder.CreateStructGEP(Dest, 1, "dst.adj"); 2963023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 2973023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall bool DerivedToBase = 2983023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer; 2993023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3003023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall const CXXRecordDecl *BaseDecl, *DerivedDecl; 3013023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall if (DerivedToBase) 3023023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall DerivedDecl = SrcDecl, BaseDecl = DestDecl; 3033023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall else 3043023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall BaseDecl = SrcDecl, DerivedDecl = DestDecl; 3053023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3063023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall if (llvm::Constant *Adj = 3073023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall CGF.CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 3083023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->path_begin(), 3093023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall E->path_end())) { 310875ab10245d3bf37252dd822aa1616bb0a391095John McCall // The this-adjustment is left-shifted by 1 on ARM. 311875ab10245d3bf37252dd822aa1616bb0a391095John McCall if (IsARM) { 312875ab10245d3bf37252dd822aa1616bb0a391095John McCall uint64_t Offset = cast<llvm::ConstantInt>(Adj)->getZExtValue(); 313875ab10245d3bf37252dd822aa1616bb0a391095John McCall Offset <<= 1; 314875ab10245d3bf37252dd822aa1616bb0a391095John McCall Adj = llvm::ConstantInt::get(Adj->getType(), Offset); 315875ab10245d3bf37252dd822aa1616bb0a391095John McCall } 316875ab10245d3bf37252dd822aa1616bb0a391095John McCall 3173023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall if (DerivedToBase) 3183023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall SrcAdj = Builder.CreateSub(SrcAdj, Adj, "adj"); 3193023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall else 3203023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall SrcAdj = Builder.CreateAdd(SrcAdj, Adj, "adj"); 3213023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall } 3223023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall 3233023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall Builder.CreateStore(SrcAdj, DstAdj, VolatileDest); 3243023def6bea3af6dbb51eea51f8cb8ea892d26cfJohn McCall} 325cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 326cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallllvm::Constant * 327cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallItaniumCXXABI::EmitMemberFunctionPointerConversion(llvm::Constant *C, 328cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const CastExpr *E) { 329cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *SrcTy = 330cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->getSubExpr()->getType()->getAs<MemberPointerType>(); 331cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *DestTy = 332cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->getType()->getAs<MemberPointerType>(); 333cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 334cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool DerivedToBase = 335cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->getCastKind() == CastExpr::CK_DerivedToBaseMemberPointer; 336cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 337cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const CXXRecordDecl *DerivedDecl; 338cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall if (DerivedToBase) 339cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall DerivedDecl = SrcTy->getClass()->getAsCXXRecordDecl(); 340cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall else 341cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall DerivedDecl = DestTy->getClass()->getAsCXXRecordDecl(); 342cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 343cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // Calculate the offset to the base class. 344cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Constant *Offset = 345cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall CGM.GetNonVirtualBaseClassOffset(DerivedDecl, 346cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->path_begin(), 347cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall E->path_end()); 348cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // If there's no offset, we're done. 349cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall if (!Offset) return C; 350cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 351875ab10245d3bf37252dd822aa1616bb0a391095John McCall // The this-adjustment is left-shifted by 1 on ARM. 352875ab10245d3bf37252dd822aa1616bb0a391095John McCall if (IsARM) { 353875ab10245d3bf37252dd822aa1616bb0a391095John McCall uint64_t OffsetV = cast<llvm::ConstantInt>(Offset)->getZExtValue(); 354875ab10245d3bf37252dd822aa1616bb0a391095John McCall OffsetV <<= 1; 355875ab10245d3bf37252dd822aa1616bb0a391095John McCall Offset = llvm::ConstantInt::get(Offset->getType(), OffsetV); 356875ab10245d3bf37252dd822aa1616bb0a391095John McCall } 357875ab10245d3bf37252dd822aa1616bb0a391095John McCall 358cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::ConstantStruct *CS = cast<llvm::ConstantStruct>(C); 359cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 360cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Constant *Values[2] = { 361cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall CS->getOperand(0), 362cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::ConstantExpr::getAdd(CS->getOperand(1), Offset) 363cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall }; 364cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall return llvm::ConstantStruct::get(CGM.getLLVMContext(), Values, 2, 365cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall /*Packed=*/false); 366cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 367cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 368cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 369cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallvoid ItaniumCXXABI::EmitNullMemberFunctionPointer(CodeGenFunction &CGF, 370cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const MemberPointerType *MPT, 371cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Dest, 372cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall bool VolatileDest) { 373cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // Should this be "unabstracted" and implemented in terms of the 374cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall // Constant version? 375cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 376cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall CGBuilderTy &Builder = CGF.Builder; 377cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 378cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall const llvm::IntegerType *PtrDiffTy = CGF.IntPtrTy; 379cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Zero = llvm::ConstantInt::get(PtrDiffTy, 0); 380cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 381cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Ptr = Builder.CreateStructGEP(Dest, 0, "ptr"); 382cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall Builder.CreateStore(Zero, Ptr, VolatileDest); 383cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 384cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall llvm::Value *Adj = Builder.CreateStructGEP(Dest, 1, "adj"); 385cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall Builder.CreateStore(Zero, Adj, VolatileDest); 386cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 387cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 388cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallllvm::Constant * 389cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallItaniumCXXABI::EmitNullMemberFunctionPointer(const MemberPointerType *MPT) { 390cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall return CGM.EmitNullConstant(QualType(MPT, 0)); 391cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 392cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 393875ab10245d3bf37252dd822aa1616bb0a391095John McCallllvm::Constant * 394875ab10245d3bf37252dd822aa1616bb0a391095John McCallItaniumCXXABI::EmitMemberFunctionPointer(const CXXMethodDecl *MD) { 395875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Constant *Values[2]; 396875ab10245d3bf37252dd822aa1616bb0a391095John McCall GetMemberFunctionPointer(MD, Values); 397875ab10245d3bf37252dd822aa1616bb0a391095John McCall 398875ab10245d3bf37252dd822aa1616bb0a391095John McCall return llvm::ConstantStruct::get(CGM.getLLVMContext(), 399875ab10245d3bf37252dd822aa1616bb0a391095John McCall Values, 2, /*Packed=*/false); 400875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 401875ab10245d3bf37252dd822aa1616bb0a391095John McCall 402875ab10245d3bf37252dd822aa1616bb0a391095John McCallvoid ItaniumCXXABI::EmitMemberFunctionPointer(CodeGenFunction &CGF, 403875ab10245d3bf37252dd822aa1616bb0a391095John McCall const CXXMethodDecl *MD, 404875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Value *DestPtr, 405875ab10245d3bf37252dd822aa1616bb0a391095John McCall bool VolatileDest) { 406875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Constant *Values[2]; 407875ab10245d3bf37252dd822aa1616bb0a391095John McCall GetMemberFunctionPointer(MD, Values); 408875ab10245d3bf37252dd822aa1616bb0a391095John McCall 409875ab10245d3bf37252dd822aa1616bb0a391095John McCall CGBuilderTy &Builder = CGF.Builder; 410875ab10245d3bf37252dd822aa1616bb0a391095John McCall 411875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Value *DstPtr = Builder.CreateStructGEP(DestPtr, 0, "memptr.ptr"); 412875ab10245d3bf37252dd822aa1616bb0a391095John McCall Builder.CreateStore(Values[0], DstPtr, VolatileDest); 413875ab10245d3bf37252dd822aa1616bb0a391095John McCall 414875ab10245d3bf37252dd822aa1616bb0a391095John McCall llvm::Value *AdjPtr = Builder.CreateStructGEP(DestPtr, 1, "memptr.adj"); 415875ab10245d3bf37252dd822aa1616bb0a391095John McCall Builder.CreateStore(Values[1], AdjPtr, VolatileDest); 416875ab10245d3bf37252dd822aa1616bb0a391095John McCall} 417875ab10245d3bf37252dd822aa1616bb0a391095John McCall 418e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// The comparison algorithm is pretty easy: the member pointers are 419e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// the same if they're either bitwise identical *or* both null. 420e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// 421e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall/// ARM is different here only because null-ness is more complicated. 422e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 423e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallItaniumCXXABI::EmitMemberFunctionPointerComparison(CodeGenFunction &CGF, 424e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *L, 425e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *R, 426e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall const MemberPointerType *MPT, 427e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall bool Inequality) { 428e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 429e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 430e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *LPtr = Builder.CreateLoad(Builder.CreateStructGEP(L, 0), 431e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "lhs.memptr.ptr"); 432e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *RPtr = Builder.CreateLoad(Builder.CreateStructGEP(R, 0), 433e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "rhs.memptr.ptr"); 434e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 435e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // The Itanium tautology is: 436e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // (L == R) <==> (L.ptr == R.ptr /\ (L.ptr == 0 \/ L.adj == R.adj)) 437e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // The ARM tautology is: 438e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // (L == R) <==> (L.ptr == R.ptr /\ 439e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // (L.adj == R.adj \/ 440e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // (L.ptr == 0 /\ ((L.adj|R.adj) & 1) == 0))) 441e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // The inequality tautologies have exactly the same structure, except 442e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // applying De Morgan's laws. 443e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 444e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::ICmpInst::Predicate Eq; 445e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Instruction::BinaryOps And, Or; 446e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (Inequality) { 447e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_NE; 448e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::Or; 449e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::And; 450e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } else { 451e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Eq = llvm::ICmpInst::ICMP_EQ; 452e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall And = llvm::Instruction::And; 453e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Or = llvm::Instruction::Or; 454e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 455e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 456e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.ptr == R.ptr. This must always be 457e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true for equality to hold. 458e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *PtrEq = Builder.CreateICmp(Eq, LPtr, RPtr, "cmp.ptr"); 459e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 460e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition, together with the assumption that L.ptr == R.ptr, 461e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // tests whether the pointers are both null. ARM imposes an extra 462e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // condition. 463e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Zero = llvm::Constant::getNullValue(LPtr->getType()); 464e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *EqZero = Builder.CreateICmp(Eq, LPtr, Zero, "cmp.ptr.null"); 465e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 466e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // This condition tests whether L.adj == R.adj. If this isn't 467e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // true, the pointers are unequal unless they're both null. 468e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *LAdj = Builder.CreateLoad(Builder.CreateStructGEP(L, 1), 469e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "lhs.memptr.adj"); 470e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *RAdj = Builder.CreateLoad(Builder.CreateStructGEP(R, 1), 471e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "rhs.memptr.adj"); 472e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *AdjEq = Builder.CreateICmp(Eq, LAdj, RAdj, "cmp.adj"); 473e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 474e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Null member function pointers on ARM clear the low bit of Adj, 475e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // so the zero condition has to check that neither low bit is set. 476e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 477e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *One = llvm::ConstantInt::get(LPtr->getType(), 1); 478e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 479e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Compute (l.adj | r.adj) & 1 and test it against zero. 480e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj"); 481e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One); 482e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero, 483e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "cmp.or.adj"); 484e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero); 485e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 486e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 487e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // Tie together all our conditions. 488e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateBinOp(Or, EqZero, AdjEq); 489e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Result = Builder.CreateBinOp(And, PtrEq, Result, 490e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Inequality ? "memptr.ne" : "memptr.eq"); 491e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 492e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 493e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 494e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallllvm::Value * 495e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCallItaniumCXXABI::EmitMemberFunctionPointerIsNotNull(CodeGenFunction &CGF, 496e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *MemPtr, 497e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall const MemberPointerType *MPT) { 498e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall CGBuilderTy &Builder = CGF.Builder; 499e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 500e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // In Itanium, a member function pointer is null if 'ptr' is null. 501e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Ptr = 502e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Builder.CreateLoad(Builder.CreateStructGEP(MemPtr, 0), "memptr.ptr"); 503e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 504e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *Zero = llvm::ConstantInt::get(Ptr->getType(), 0); 505e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Result = Builder.CreateICmpNE(Ptr, Zero, "memptr.tobool"); 506e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 507e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall // In ARM, it's that, plus the low bit of 'adj' must be zero. 508e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall if (IsARM) { 509e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1); 510e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *Adj = 511e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Builder.CreateLoad(Builder.CreateStructGEP(MemPtr, 1), "memptr.adj"); 512e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit"); 513e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall llvm::Value *IsNotVirtual = Builder.CreateICmpEQ(VirtualBit, Zero, 514e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall "memptr.notvirtual"); 515e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall Result = Builder.CreateAnd(Result, IsNotVirtual); 516e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall } 517e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall 518e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall return Result; 519e9fd7eb6c67676dc27e84eac429aec4f3be51f26John McCall} 520875ab10245d3bf37252dd822aa1616bb0a391095John McCall 521cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallbool ItaniumCXXABI::RequiresNonZeroInitializer(QualType T) { 522cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall return CGM.getTypes().ContainsPointerToDataMember(T); 523cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 524cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall 525cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCallbool ItaniumCXXABI::RequiresNonZeroInitializer(const CXXRecordDecl *D) { 526cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall return CGM.getTypes().ContainsPointerToDataMember(D); 527cf2c85e76fdafe7e634810a292321a6c8322483dJohn McCall} 528