CGClass.cpp revision 9fcfc421d3bf124beed5b185b8d6d795edcbf83a
15b955920c1d8f2cd35aae3c85b656578286a8bc1Anders Carlsson//===--- CGClass.cpp - Emit LLVM Code for C++ classes ---------------------===// 25d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// 35d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// The LLVM Compiler Infrastructure 45d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// 55d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// This file is distributed under the University of Illinois Open Source 65d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// License. See LICENSE.TXT for details. 75d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// 85d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson//===----------------------------------------------------------------------===// 95d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// 105d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// This contains code dealing with C++ code generation of classes 115d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson// 125d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson//===----------------------------------------------------------------------===// 135d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 145d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson#include "CodeGenFunction.h" 152f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson#include "clang/AST/CXXInheritance.h" 165d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson#include "clang/AST/RecordLayout.h" 172f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 185d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlssonusing namespace clang; 195d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlssonusing namespace CodeGen; 205d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 212f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlssonstatic uint64_t 222f1986b557fa671c4f8c9dd0d071398edfc073d5Anders CarlssonComputeNonVirtualBaseClassOffset(ASTContext &Context, CXXBasePaths &Paths, 232f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson unsigned Start) { 242f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson uint64_t Offset = 0; 255d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 262f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const CXXBasePath &Path = Paths.front(); 272f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson for (unsigned i = Start, e = Path.size(); i != e; ++i) { 282f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const CXXBasePathElement& Element = Path[i]; 295d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 302f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson // Get the layout. 312f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const ASTRecordLayout &Layout = Context.getASTRecordLayout(Element.Class); 325d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 332f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const CXXBaseSpecifier *BS = Element.Base; 342f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson assert(!BS->isVirtual() && "Should not see virtual bases here!"); 355d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 362f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const CXXRecordDecl *Base = 372f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson cast<CXXRecordDecl>(BS->getType()->getAs<RecordType>()->getDecl()); 382f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 392f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson // Add the offset. 402f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson Offset += Layout.getBaseClassOffset(Base) / 8; 412f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson } 422f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 432f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson return Offset; 445d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson} 455d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 4684080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlssonllvm::Constant * 472b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders CarlssonCodeGenModule::GetCXXBaseClassOffset(const CXXRecordDecl *ClassDecl, 482b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson const CXXRecordDecl *BaseClassDecl) { 4984080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson if (ClassDecl == BaseClassDecl) 5084080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson return 0; 5184080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson 522f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson CXXBasePaths Paths(/*FindAmbiguities=*/false, 532f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson /*RecordPaths=*/true, /*DetectVirtual=*/false); 542f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson if (!const_cast<CXXRecordDecl *>(ClassDecl)-> 552f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) { 562f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson assert(false && "Class must be derived from the passed in base class!"); 572f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson return 0; 582f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson } 5984080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson 602f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson uint64_t Offset = ComputeNonVirtualBaseClassOffset(getContext(), Paths, 0); 6184080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson if (!Offset) 6284080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson return 0; 6384080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson 642b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson const llvm::Type *PtrDiffTy = 652b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson Types.ConvertType(getContext().getPointerDiffType()); 6684080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson 6784080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson return llvm::ConstantInt::get(PtrDiffTy, Offset); 6884080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson} 6984080ec16ede6a6fe85a1d991690c6bda82a59eeAnders Carlsson 702f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlssonstatic llvm::Value *GetCXXBaseClassOffset(CodeGenFunction &CGF, 712f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson llvm::Value *BaseValue, 722f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const CXXRecordDecl *ClassDecl, 732f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const CXXRecordDecl *BaseClassDecl) { 742f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson CXXBasePaths Paths(/*FindAmbiguities=*/false, 758432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman /*RecordPaths=*/true, /*DetectVirtual=*/false); 762f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson if (!const_cast<CXXRecordDecl *>(ClassDecl)-> 772f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) { 782f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson assert(false && "Class must be derived from the passed in base class!"); 792f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson return 0; 802f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson } 812f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 822f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson unsigned Start = 0; 832f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson llvm::Value *VirtualOffset = 0; 848432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman 858432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman const CXXBasePath &Path = Paths.front(); 868432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman const CXXRecordDecl *VBase = 0; 878432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman for (unsigned i = 0, e = Path.size(); i != e; ++i) { 888432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman const CXXBasePathElement& Element = Path[i]; 898432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman if (Element.Base->isVirtual()) { 908432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman Start = i+1; 918432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman QualType VBaseType = Element.Base->getType(); 928432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman VBase = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl()); 932f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson } 942f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson } 958432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman if (VBase) 968432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman VirtualOffset = 978432f25cb242cbc809f9b10672e8e2074d362f80Eli Friedman CGF.GetVirtualCXXBaseClassOffset(BaseValue, ClassDecl, VBase); 982f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 992f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson uint64_t Offset = 1002f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson ComputeNonVirtualBaseClassOffset(CGF.getContext(), Paths, Start); 1012f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 1022f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson if (!Offset) 1032f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson return VirtualOffset; 1042f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 1052f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson const llvm::Type *PtrDiffTy = 1062f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson CGF.ConvertType(CGF.getContext().getPointerDiffType()); 1072f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson llvm::Value *NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, Offset); 1082f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 1092f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson if (VirtualOffset) 1102f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson return CGF.Builder.CreateAdd(VirtualOffset, NonVirtualOffset); 1112f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 1122f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson return NonVirtualOffset; 1132f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson} 1142f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson 1159fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson// FIXME: This probably belongs in CGVtable, but it relies on 1169fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson// the static function ComputeNonVirtualBaseClassOffset, so we should make that 1179fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson// a CodeGenModule member function as well. 1189fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders CarlssonThunkAdjustment 1199fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders CarlssonCodeGenModule::ComputeThunkAdjustment(const CXXRecordDecl *ClassDecl, 1209fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson const CXXRecordDecl *BaseClassDecl) { 1219fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson CXXBasePaths Paths(/*FindAmbiguities=*/false, 1229fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson /*RecordPaths=*/true, /*DetectVirtual=*/false); 1239fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson if (!const_cast<CXXRecordDecl *>(ClassDecl)-> 1249fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson isDerivedFrom(const_cast<CXXRecordDecl *>(BaseClassDecl), Paths)) { 1259fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson assert(false && "Class must be derived from the passed in base class!"); 1269fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson return ThunkAdjustment(); 1279fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson } 1289fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson 1299fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson unsigned Start = 0; 1309fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson uint64_t VirtualOffset = 0; 1319fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson 1329fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson const CXXBasePath &Path = Paths.front(); 1339fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson const CXXRecordDecl *VBase = 0; 1349fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson for (unsigned i = 0, e = Path.size(); i != e; ++i) { 1359fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson const CXXBasePathElement& Element = Path[i]; 1369fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson if (Element.Base->isVirtual()) { 1379fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson Start = i+1; 1389fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson QualType VBaseType = Element.Base->getType(); 1399fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson VBase = cast<CXXRecordDecl>(VBaseType->getAs<RecordType>()->getDecl()); 1409fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson } 1419fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson } 1429fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson if (VBase) 1439fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson VirtualOffset = 1449fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl); 1459fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson 1469fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson uint64_t Offset = 1479fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson ComputeNonVirtualBaseClassOffset(getContext(), Paths, Start); 1489fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson return ThunkAdjustment(Offset, VirtualOffset); 1499fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson} 1509fcfc421d3bf124beed5b185b8d6d795edcbf83aAnders Carlsson 1515d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlssonllvm::Value * 152a3697c9c155bda93fd2802f37084b620f4738822Anders CarlssonCodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value, 153a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson const CXXRecordDecl *ClassDecl, 154a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson const CXXRecordDecl *BaseClassDecl, 155a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson bool NullCheckValue) { 156dfd0330267742862342976eb7f2d5ef305790df4Anders Carlsson QualType BTy = 157dfd0330267742862342976eb7f2d5ef305790df4Anders Carlsson getContext().getCanonicalType( 158dfd0330267742862342976eb7f2d5ef305790df4Anders Carlsson getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClassDecl))); 159dfd0330267742862342976eb7f2d5ef305790df4Anders Carlsson const llvm::Type *BasePtrTy = llvm::PointerType::getUnqual(ConvertType(BTy)); 1605d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 1612f1986b557fa671c4f8c9dd0d071398edfc073d5Anders Carlsson if (ClassDecl == BaseClassDecl) { 162dfd0330267742862342976eb7f2d5ef305790df4Anders Carlsson // Just cast back. 163a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson return Builder.CreateBitCast(Value, BasePtrTy); 164dfd0330267742862342976eb7f2d5ef305790df4Anders Carlsson } 1654a5dc242545222aef6313cc4297708f524e10c6fEli Friedman 16632baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson llvm::BasicBlock *CastNull = 0; 16732baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson llvm::BasicBlock *CastNotNull = 0; 16832baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson llvm::BasicBlock *CastEnd = 0; 16932baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson 17032baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson if (NullCheckValue) { 17132baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson CastNull = createBasicBlock("cast.null"); 17232baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson CastNotNull = createBasicBlock("cast.notnull"); 17332baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson CastEnd = createBasicBlock("cast.end"); 17432baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson 17532baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson llvm::Value *IsNull = 176a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Builder.CreateICmpEQ(Value, 177a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::Constant::getNullValue(Value->getType())); 17832baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson Builder.CreateCondBr(IsNull, CastNull, CastNotNull); 17932baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson EmitBlock(CastNotNull); 18032baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson } 18132baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson 1823c0ef8cc0dc246bd3083e8cdd63005e8873d36d2Benjamin Kramer const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); 1834a5dc242545222aef6313cc4297708f524e10c6fEli Friedman 1844a5dc242545222aef6313cc4297708f524e10c6fEli Friedman llvm::Value *Offset = 185a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson GetCXXBaseClassOffset(*this, Value, ClassDecl, BaseClassDecl); 1865d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 1874a5dc242545222aef6313cc4297708f524e10c6fEli Friedman if (Offset) { 1884a5dc242545222aef6313cc4297708f524e10c6fEli Friedman // Apply the offset. 189a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = Builder.CreateBitCast(Value, Int8PtrTy); 190a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = Builder.CreateGEP(Value, Offset, "add.ptr"); 1914a5dc242545222aef6313cc4297708f524e10c6fEli Friedman } 1925d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 1935d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson // Cast back. 194a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = Builder.CreateBitCast(Value, BasePtrTy); 19532baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson 19632baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson if (NullCheckValue) { 19732baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson Builder.CreateBr(CastEnd); 19832baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson EmitBlock(CastNull); 19932baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson Builder.CreateBr(CastEnd); 20032baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson EmitBlock(CastEnd); 20132baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson 202a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(Value->getType()); 203a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson PHI->reserveOperandSpace(2); 204a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson PHI->addIncoming(Value, CastNotNull); 205a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), 206a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson CastNull); 207a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = PHI; 208a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson } 209a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 210a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson return Value; 211a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson} 212a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 213a3697c9c155bda93fd2802f37084b620f4738822Anders Carlssonllvm::Value * 214a3697c9c155bda93fd2802f37084b620f4738822Anders CarlssonCodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value, 215a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson const CXXRecordDecl *ClassDecl, 216a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson const CXXRecordDecl *DerivedClassDecl, 217a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson bool NullCheckValue) { 218a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson QualType DerivedTy = 219a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson getContext().getCanonicalType( 220a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(DerivedClassDecl))); 221a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo(); 222a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 223a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson if (ClassDecl == DerivedClassDecl) { 224a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson // Just cast back. 225a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson return Builder.CreateBitCast(Value, DerivedPtrTy); 226a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson } 227a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 228a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::BasicBlock *CastNull = 0; 229a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::BasicBlock *CastNotNull = 0; 230a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::BasicBlock *CastEnd = 0; 231a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 232a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson if (NullCheckValue) { 233a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson CastNull = createBasicBlock("cast.null"); 234a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson CastNotNull = createBasicBlock("cast.notnull"); 235a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson CastEnd = createBasicBlock("cast.end"); 236a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 237a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::Value *IsNull = 238a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Builder.CreateICmpEQ(Value, 239a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::Constant::getNullValue(Value->getType())); 240a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Builder.CreateCondBr(IsNull, CastNull, CastNotNull); 241a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson EmitBlock(CastNotNull); 242a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson } 243a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 244a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::Value *Offset = GetCXXBaseClassOffset(*this, Value, DerivedClassDecl, 245a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson ClassDecl); 246a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson if (Offset) { 247a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson // Apply the offset. 248a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = Builder.CreatePtrToInt(Value, Offset->getType()); 249a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = Builder.CreateSub(Value, Offset); 250a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = Builder.CreateIntToPtr(Value, DerivedPtrTy); 251a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson } else { 252a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson // Just cast. 253a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = Builder.CreateBitCast(Value, DerivedPtrTy); 254a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson } 255a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 256a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson if (NullCheckValue) { 257a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Builder.CreateBr(CastEnd); 258a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson EmitBlock(CastNull); 259a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Builder.CreateBr(CastEnd); 260a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson EmitBlock(CastEnd); 261a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson 262a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(Value->getType()); 26332baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson PHI->reserveOperandSpace(2); 264a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson PHI->addIncoming(Value, CastNotNull); 265a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), 26632baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson CastNull); 267a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson Value = PHI; 26832baf62b9a3aea3b63be6925b64aa182b0a2278eAnders Carlsson } 2695d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson 270a3697c9c155bda93fd2802f37084b620f4738822Anders Carlsson return Value; 2715d58a1d50e2644668122b8efb6b603a706ecfd6bAnders Carlsson} 272