CGCXX.cpp revision 2b3583573ba6b26b605aacaad9a50492fb3d6fe6
1e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson//===--- CGDecl.cpp - Emit LLVM Code for declarations ---------------------===// 2e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// 3e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// The LLVM Compiler Infrastructure 4e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// 5e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// This file is distributed under the University of Illinois Open Source 6e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// License. See LICENSE.TXT for details. 7e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// 8e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson//===----------------------------------------------------------------------===// 9e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// 10e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// This contains code dealing with C++ code generation. 11e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// 12e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson//===----------------------------------------------------------------------===// 13e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// We might split this into multiple files if it gets too unwieldy 15e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 16e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson#include "CodeGenFunction.h" 17e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson#include "CodeGenModule.h" 18283a062a633d6e868aa2be319da812341fe73728Anders Carlsson#include "Mangle.h" 19e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson#include "clang/AST/ASTContext.h" 20742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian#include "clang/AST/RecordLayout.h" 21e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson#include "clang/AST/Decl.h" 22774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson#include "clang/AST/DeclCXX.h" 2386e9644199d91a33d0090395395bc718bd3a4981Anders Carlsson#include "clang/AST/DeclObjC.h" 246815e941998659a55c20c147861b0f437928c3d8Anders Carlsson#include "clang/AST/StmtCXX.h" 25e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson#include "llvm/ADT/StringExtras.h" 26e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlssonusing namespace clang; 27e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlssonusing namespace CodeGen; 28e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 303b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders CarlssonCodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor, 313b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DeclPtr) { 326815e941998659a55c20c147861b0f437928c3d8Anders Carlsson const llvm::Type *Int8PtrTy = 336815e941998659a55c20c147861b0f437928c3d8Anders Carlsson llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 353b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson std::vector<const llvm::Type *> Params; 363b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 383b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // Get the destructor function type 391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *DtorFnTy = 400032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 413b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); 421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 433b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.clear(); 443b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(DtorFnTy); 453b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 463b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 483b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // Get the __cxa_atexit function type 493b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); 501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::FunctionType *AtExitFnTy = 513b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); 521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 533b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, 543b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "__cxa_atexit"); 551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 563b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, 573b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "__dso_handle"); 581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 593b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); 601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 613b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy), 623b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy), 633b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) }; 643b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); 653b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson} 663b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, 683b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DeclPtr) { 693b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson assert(D.hasGlobalStorage() && 703b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "VarDecl must have global storage!"); 711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 723b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson const Expr *Init = D.getInit(); 733b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson QualType T = D.getType(); 741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 753b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson if (T->isReferenceType()) { 76622f9dc76bdc4f4d6920907f4fb64a3222aa6566Anders Carlsson ErrorUnsupported(Init, "global variable that binds to a reference"); 773b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } else if (!hasAggregateLLVMType(T)) { 783b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Value *V = EmitScalarExpr(Init); 793b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitStoreOfScalar(V, DeclPtr, T.isVolatileQualified(), T); 803b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } else if (T->isAnyComplexType()) { 813b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitComplexExprIntoAddr(Init, DeclPtr, T.isVolatileQualified()); 823b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } else { 833b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitAggExpr(Init, DeclPtr, T.isVolatileQualified()); 841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 853b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson if (const RecordType *RT = T->getAs<RecordType>()) { 863b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 873b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson if (!RD->hasTrivialDestructor()) 883b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitCXXGlobalDtorRegistration(RD->getDestructor(getContext()), DeclPtr); 893b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } 903b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } 913b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson} 923b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 9389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlssonvoid 9489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders CarlssonCodeGenModule::EmitCXXGlobalInitFunc() { 9589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson if (CXXGlobalInits.empty()) 9689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson return; 971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 980032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 9989ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson false); 1001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10189ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson // Create our global initialization function. 10289ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson // FIXME: Should this be tweakable by targets? 1031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Function *Fn = 10489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 10589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson "__cxx_global_initialization", &TheModule); 1061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 10810c40eee98c600d24437474463b056f323d0cfd2Benjamin Kramer &CXXGlobalInits[0], 10989ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson CXXGlobalInits.size()); 11089ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson AddGlobalCtor(Fn); 11189ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson} 11289ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 11389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlssonvoid CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, 11489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson const VarDecl **Decls, 11589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson unsigned NumDecls) { 1160ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 11789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson SourceLocation()); 1181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11989ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson for (unsigned i = 0; i != NumDecls; ++i) { 12089ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson const VarDecl *D = Decls[i]; 1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12289ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); 12389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson EmitCXXGlobalVarDeclInit(*D, DeclPtr); 12489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson } 12589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson FinishFunction(); 12689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson} 12789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 1281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 1291eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, 1303b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::GlobalVariable *GV) { 1310096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbar // FIXME: This should use __cxa_guard_{acquire,release}? 1320096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbar 133e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson assert(!getContext().getLangOptions().ThreadsafeStatics && 134e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson "thread safe statics are currently not supported!"); 135e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 136283a062a633d6e868aa2be319da812341fe73728Anders Carlsson llvm::SmallString<256> GuardVName; 137283a062a633d6e868aa2be319da812341fe73728Anders Carlsson llvm::raw_svector_ostream GuardVOut(GuardVName); 138283a062a633d6e868aa2be319da812341fe73728Anders Carlsson mangleGuardVariable(&D, getContext(), GuardVOut); 1391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 140e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Create the guard variable. 1411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::GlobalValue *GuardV = 1420032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext), false, 1430096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbar GV->getLinkage(), 1440032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)), 1457765934ad7e157b5fcf925792a38e01b1edbcf8aDaniel Dunbar GuardVName.str()); 1461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 147e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Load the first byte of the guard variable. 1480032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 1491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy), 150e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson "tmp"); 1511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Compare it against 0. 1530032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)); 154e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool"); 1551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15655e874299f2ad827646a4ca9ea38c402aaeb38c9Daniel Dunbar llvm::BasicBlock *InitBlock = createBasicBlock("init"); 1579615ecb44f549ae9fa2b4db6ff46bc78befbf62cDaniel Dunbar llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); 158e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 159e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // If the guard variable is 0, jump to the initializer code. 160e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson Builder.CreateCondBr(ICmp, InitBlock, EndBlock); 1611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 162e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson EmitBlock(InitBlock); 163e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 1643b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitCXXGlobalVarDeclInit(D, GV); 1653b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 1660032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1), 167e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson Builder.CreateBitCast(GuardV, PtrTy)); 1681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 169e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson EmitBlock(EndBlock); 170e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson} 171e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 172b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders CarlssonRValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, 173b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *Callee, 174b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *This, 175b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CallExpr::const_arg_iterator ArgBeg, 176b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CallExpr::const_arg_iterator ArgEnd) { 1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(MD->isInstance() && 178774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson "Trying to emit a member call expr on a static method!"); 179b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 1804fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor // A call to a trivial destructor requires no code generation. 1814fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor if (const CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(MD)) 1824fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor if (Destructor->isTrivial()) 1834fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor return RValue::get(0); 1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 185183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 1861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 187b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CallArgList Args; 1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 189b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson // Push the this ptr. 190b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson Args.push_back(std::make_pair(RValue::get(This), 191b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson MD->getThisType(getContext()))); 1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 193b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson // And the rest of the call args 194b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); 1951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 196183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); 197b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), 198b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson Callee, Args, MD); 199b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson} 200b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 201b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders CarlssonRValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { 202b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()); 203b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); 204b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 2052472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson if (MD->isStatic()) { 2062472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson // The method is static, emit it as we would a regular call. 2072472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson llvm::Value *Callee = CGM.GetAddrOfFunction(MD); 2082472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson return EmitCall(Callee, getContext().getPointerType(MD->getType()), 2092472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson CE->arg_begin(), CE->arg_end(), 0); 2102472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson 2112472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson } 2122472bf0a1735fa9c60a01946d5ed53b64c9c2422Anders Carlsson 213183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 2147116da1efe23f90eb22524ac9aa036153b74f482Mike Stump 2151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *Ty = 2161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 217e9918d2443ad524e0f488e8f15d9bce4e7373cd1Anders Carlsson FPT->isVariadic()); 218b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *This; 2191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 220774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson if (ME->isArrow()) 221b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson This = EmitScalarExpr(ME->getBase()); 222774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson else { 223774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson LValue BaseLV = EmitLValue(ME->getBase()); 224b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson This = BaseLV.getAddress(); 225774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson } 226f0070dbae9535836ad41711081465dec2259786bMike Stump 227bd4c4aebe6035e7a7125470cc9f0f92511230ee3Douglas Gregor // C++ [class.virtual]p12: 2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Explicit qualification with the scope operator (5.1) suppresses the 229bd4c4aebe6035e7a7125470cc9f0f92511230ee3Douglas Gregor // virtual call mechanism. 230f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::Value *Callee; 2310979c805475d1ba49b5d6ef93c4d2ce6d2eab6edDouglas Gregor if (MD->isVirtual() && !ME->hasQualifier()) 232740256bafbba6c5b5cb95a5c5bd7db161f3b2833Mike Stump // FIXME: push getCanonicalDecl as a conversion using the static type system (CanCXXMethodDecl). 233740256bafbba6c5b5cb95a5c5bd7db161f3b2833Mike Stump Callee = BuildVirtualCall(MD->getCanonicalDecl(), This, Ty); 2341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (const CXXDestructorDecl *Destructor 2354fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor = dyn_cast<CXXDestructorDecl>(MD)) 2364fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); 2370979c805475d1ba49b5d6ef93c4d2ce6d2eab6edDouglas Gregor else 238555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson Callee = CGM.GetAddrOfFunction(MD, Ty); 2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return EmitCXXMemberCall(MD, Callee, This, 241b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CE->arg_begin(), CE->arg_end()); 242774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson} 2435f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson 2441eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpRValue 2450f294632f36459174199b77699e339715244b5abAnders CarlssonCodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, 2460f294632f36459174199b77699e339715244b5abAnders Carlsson const CXXMethodDecl *MD) { 2471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(MD->isInstance() && 2480f294632f36459174199b77699e339715244b5abAnders Carlsson "Trying to emit a member call expr on a static method!"); 2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 250ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian if (MD->isCopyAssignment()) { 251ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext()); 252ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian if (ClassDecl->hasTrivialCopyAssignment()) { 253ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyAssignment() && 254ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); 255ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 256ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); 257ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian QualType Ty = E->getType(); 258ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian EmitAggregateCopy(This, Src, Ty); 259ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian return RValue::get(This); 260ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian } 261ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian } 2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 263183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 2641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *Ty = 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 266ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FPT->isVariadic()); 267555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, Ty); 2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2690f294632f36459174199b77699e339715244b5abAnders Carlsson llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 2701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2710f294632f36459174199b77699e339715244b5abAnders Carlsson return EmitCXXMemberCall(MD, Callee, This, 2720f294632f36459174199b77699e339715244b5abAnders Carlsson E->arg_begin() + 1, E->arg_end()); 2730f294632f36459174199b77699e339715244b5abAnders Carlsson} 2740f294632f36459174199b77699e339715244b5abAnders Carlsson 2755f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlssonllvm::Value *CodeGenFunction::LoadCXXThis() { 2761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(isa<CXXMethodDecl>(CurFuncDecl) && 2775f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson "Must be in a C++ member function decl to load 'this'"); 2785f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() && 2795f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson "Must be in a C++ member function decl to load 'this'"); 2801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2815f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson // FIXME: What if we're inside a block? 282f5408fe484495ee4efbdd709c8a2c2fdbbbdb328Mike Stump // ans: See how CodeGenFunction::LoadObjCSelf() uses 283f5408fe484495ee4efbdd709c8a2c2fdbbbdb328Mike Stump // CodeGenFunction::BlockForwardSelf() for how to do this. 2845f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); 2855f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson} 28695d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlsson 287288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested) 288288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// for-loop to call the default constructor on individual members of the 289569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson/// array. 290569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson/// 'D' is the default constructor for elements of the array, 'ArrayTy' is the 291569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson/// array type and 'ArrayPtr' points to the beginning fo the array. 292569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson/// It is assumed that all relevant checks have been made by the caller. 293288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanianvoid 294288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz JahanianCodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, 295569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson const ConstantArrayType *ArrayTy, 296569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *ArrayPtr) { 297569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 298569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value * NumElements = 299569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::ConstantInt::get(SizeTy, 300569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson getContext().getConstantArrayElementCount(ArrayTy)); 301569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson 302569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr); 303569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson} 304569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson 305569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlssonvoid 306569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders CarlssonCodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, 307569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *NumElements, 308569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *ArrayPtr) { 309569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 3101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 311288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Create a temporary for the loop index and initialize it with 0. 312569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index"); 313569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy); 314569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson Builder.CreateStore(Zero, IndexPtr, false); 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 316288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Start the loop with a block that tests the condition. 317288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 318288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 3191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 320288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(CondBlock); 3211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 322288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 3231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 324288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Generate: if (loop-index < number-of-elements fall to the loop body, 325288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // otherwise, go to the block after the for-loop. 326288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 327569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless"); 328288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // If the condition is true, execute the body. 329288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Builder.CreateCondBr(IsLess, ForBody, AfterFor); 3301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 331288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(ForBody); 3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 333288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 334288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Inside the loop body, emit the constructor call on the array element. 335995d2818a11395b15995694a30f842a0e4fdee4fFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 336569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter, 337569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson "arrayidx"); 3384f68d537c3f072366b25f3137f052eee36fddfcdFariborz Jahanian EmitCXXConstructorCall(D, Ctor_Complete, Address, 0, 0); 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 340288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(ContinueBlock); 3411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 342288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Emit the increment of the loop counter. 343569c1f4a6c703eaa8b963bed7d5c2fd5d4569e93Anders Carlsson llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1); 344288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 345288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); 346288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Builder.CreateStore(NextVal, IndexPtr, false); 3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 348288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Finally, branch back up to the condition for the next iteration. 349288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBranch(CondBlock); 3501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 351288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Emit the fall-through block. 352288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(AfterFor, true); 353288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian} 354288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian 3551c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian/// EmitCXXAggrDestructorCall - calls the default destructor on array 3561c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian/// elements in reverse order of construction. 357b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlssonvoid 358f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz JahanianCodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, 359f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian const ArrayType *Array, 360f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian llvm::Value *This) { 3611c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); 3621c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian assert(CA && "Do we support VLA for destruction ?"); 3631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 3641c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian 1); 3650de78998e7bda473b408437053e48661b510d453Fariborz Jahanian uint64_t ElementCount = getContext().getConstantArrayElementCount(CA); 3661c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Create a temporary for the loop index and initialize it with count of 3671c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // array elements. 3681c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), 3691c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian "loop.index"); 3701c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Index = ElementCount; 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* UpperCount = 3721c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount); 3731c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Builder.CreateStore(UpperCount, IndexPtr, false); 3741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3751c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Start the loop with a block that tests the condition. 3761c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 3771c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3791c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(CondBlock); 3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3811c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 3821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3831c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Generate: if (loop-index != 0 fall to the loop body, 3841c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // otherwise, go to the block after the for-loop. 3851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* zeroConstant = 3861c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); 3871c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 3881c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant, 3891c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian "isne"); 3901c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // If the condition is true, execute the body. 3911c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Builder.CreateCondBr(IsNE, ForBody, AfterFor); 3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3931c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(ForBody); 3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3951c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 3961c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Inside the loop body, emit the constructor call on the array element. 3971c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 3981c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateSub(Counter, One); 3991c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx"); 4001c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitCXXDestructorCall(D, Dtor_Complete, Address); 4011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4021c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(ContinueBlock); 4031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4041c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Emit the decrement of the loop counter. 4051c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 4061c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateSub(Counter, One, "dec"); 4071c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Builder.CreateStore(Counter, IndexPtr, false); 4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4091c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Finally, branch back up to the condition for the next iteration. 4101c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBranch(CondBlock); 4111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4121c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Emit the fall-through block. 4131c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(AfterFor, true); 414f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian} 415f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian 416f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanianvoid 4171eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, 4181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CXXCtorType Type, 419b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson llvm::Value *This, 420b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson CallExpr::const_arg_iterator ArgBeg, 421b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson CallExpr::const_arg_iterator ArgEnd) { 422343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian if (D->isCopyConstructor(getContext())) { 423343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D->getDeclContext()); 424343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian if (ClassDecl->hasTrivialCopyConstructor()) { 425343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyConstructor() && 426343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian "EmitCXXConstructorCall - user declared copy constructor"); 427343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian const Expr *E = (*ArgBeg); 428343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian QualType Ty = E->getType(); 429343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian llvm::Value *Src = EmitLValue(E).getAddress(); 430343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian EmitAggregateCopy(This, Src, Ty); 431343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian return; 432343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian } 433343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian } 4341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 435b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); 436b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 437b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson EmitCXXMemberCall(D, Callee, This, ArgBeg, ArgEnd); 438b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson} 439b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson 4401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D, 4417267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson CXXDtorType Type, 4427267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson llvm::Value *This) { 4437267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(D, Type); 4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4457267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson EmitCXXMemberCall(D, Callee, This, 0, 0); 4467267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson} 4477267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson 4481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 4491eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, 45031ccf377f4a676eb6c205b47eef435de616d5e2dAnders Carlsson const CXXConstructExpr *E) { 451b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson assert(Dest && "Must have a destination!"); 4521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *RD = 4546217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); 455b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson if (RD->hasTrivialConstructor()) 456b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson return; 4576904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian 4581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Code gen optimization to eliminate copy constructor and return 4596904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian // its first argument instead. 46092f5822df6a0d7571df44b5d279ed4f017fbb0e6Anders Carlsson if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { 4616904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian CXXConstructExpr::const_arg_iterator i = E->arg_begin(); 4621cf9ff87ee235ad252332a96699abdb32bd6facbFariborz Jahanian EmitAggExpr((*i), Dest, false); 4631cf9ff87ee235ad252332a96699abdb32bd6facbFariborz Jahanian return; 4646904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian } 465b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson // Call the constructor. 4661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest, 467b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson E->arg_begin(), E->arg_end()); 468b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson} 469b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson 47095d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlssonvoid CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { 4712a131fbca2a51085dc083b8c56a2d4ced3cf1413Anders Carlsson EmitGlobal(GlobalDecl(D, Ctor_Complete)); 4722a131fbca2a51085dc083b8c56a2d4ced3cf1413Anders Carlsson EmitGlobal(GlobalDecl(D, Ctor_Base)); 47395d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlsson} 474363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson 4751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, 47627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXCtorType Type) { 4771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type); 4791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4800ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); 4811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 48227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetFunctionDefinitionAttributes(D, Fn); 48327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetLLVMFunctionAttributesForDefinition(D, Fn); 48427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 48527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 486363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlssonllvm::Function * 4871eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, 488363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson CXXCtorType Type) { 489363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson const llvm::FunctionType *FTy = 490363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 492363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson const char *Name = getMangledCXXCtorName(D, Type); 493b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner return cast<llvm::Function>( 494b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 495363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson} 49627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 4971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpconst char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D, 49827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXCtorType Type) { 49927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::SmallString<256> Name; 50027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::raw_svector_ostream Out(Name); 50127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson mangleCXXCtor(D, Type, Context, Out); 5021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 50327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson Name += '\0'; 50427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson return UniqueMangledName(Name.begin(), Name.end()); 50527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 50627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 50727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonvoid CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) { 50827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson EmitCXXDestructor(D, Dtor_Complete); 50927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson EmitCXXDestructor(D, Dtor_Base); 51027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 51127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 5121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, 51327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 51427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type); 5151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5160ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); 5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 51827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetFunctionDefinitionAttributes(D, Fn); 51927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetLLVMFunctionAttributesForDefinition(D, Fn); 52027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 52127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 52227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonllvm::Function * 5231eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, 52427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 52527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson const llvm::FunctionType *FTy = 52627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 5271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 52827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson const char *Name = getMangledCXXDtorName(D, Type); 529b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner return cast<llvm::Function>( 530b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 53127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 53227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 5331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpconst char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, 53427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 53527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::SmallString<256> Name; 53627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::raw_svector_ostream Out(Name); 53727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson mangleCXXDtor(D, Type, Context, Out); 5381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 53927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson Name += '\0'; 54027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson return UniqueMangledName(Name.begin(), Name.end()); 54127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 542e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian 54332f3701853a8237704065c77abc17369dd02c39bMike Stumpllvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) { 544738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::Type *Ptr8Ty; 5450032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 546cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump llvm::Constant *Rtti = llvm::Constant::getNullValue(Ptr8Ty); 547738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 548738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump if (!getContext().getLangOptions().Rtti) 549cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump return Rtti; 550738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 551738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::SmallString<256> OutName; 552738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::raw_svector_ostream Out(OutName); 553738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump QualType ClassTy; 554e607ed068334bacb8d7b093996b4671c6ca79e25Mike Stump ClassTy = getContext().getTagDeclType(RD); 555738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump mangleCXXRtti(ClassTy, getContext(), Out); 556738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::GlobalVariable::LinkageTypes linktype; 557738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 558738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump std::vector<llvm::Constant *> info; 5594ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump // assert(0 && "FIXME: implement rtti descriptor"); 560738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump // FIXME: descriptor 561738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); 5624ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump // assert(0 && "FIXME: implement rtti ts"); 563738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump // FIXME: TS 564738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); 565738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 566738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::Constant *C; 567738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, info.size()); 568738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump C = llvm::ConstantArray::get(type, info); 56932f3701853a8237704065c77abc17369dd02c39bMike Stump Rtti = new llvm::GlobalVariable(getModule(), type, true, linktype, C, 5707765934ad7e157b5fcf925792a38e01b1edbcf8aDaniel Dunbar Out.str()); 571cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump Rtti = llvm::ConstantExpr::getBitCast(Rtti, Ptr8Ty); 572cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump return Rtti; 573738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump} 574738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 575eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stumpclass VtableBuilder { 576f0070dbae9535836ad41711081465dec2259786bMike Stumppublic: 577f0070dbae9535836ad41711081465dec2259786bMike Stump /// Index_t - Vtable index type. 578f0070dbae9535836ad41711081465dec2259786bMike Stump typedef uint64_t Index_t; 579f0070dbae9535836ad41711081465dec2259786bMike Stumpprivate: 5807c435fa7f7666b22abbe8494c537ebc25209223dMike Stump std::vector<llvm::Constant *> &methods; 58115a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump std::vector<llvm::Constant *> submethods; 5827c435fa7f7666b22abbe8494c537ebc25209223dMike Stump llvm::Type *Ptr8Ty; 583b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// Class - The most derived class that this vtable is being built for. 58432f3701853a8237704065c77abc17369dd02c39bMike Stump const CXXRecordDecl *Class; 585b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// BLayout - Layout for the most derived class that this vtable is being 586b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// built for. 587b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump const ASTRecordLayout &BLayout; 588ee560f3b1fda7d5ec68b85b497c3e326ac5c3fdbMike Stump llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary; 5897fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase; 59032f3701853a8237704065c77abc17369dd02c39bMike Stump llvm::Constant *rtti; 5917c435fa7f7666b22abbe8494c537ebc25209223dMike Stump llvm::LLVMContext &VMContext; 59265defe3ee7be121aef50b498e51f1d831b4a15f3Mike Stump CodeGenModule &CGM; // Per-module state. 593b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// Index - Maps a method decl into a vtable index. Useful for virtual 594b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// dispatch codegen. 595f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> Index; 59615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall; 59715a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset; 59897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex; 5996e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump typedef std::pair<Index_t, Index_t> CallOffset; 6006e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t; 60177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks_t Thunks; 6026e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump typedef llvm::DenseMap<const CXXMethodDecl *, 6036e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump std::pair<CallOffset, CallOffset> > CovariantThunks_t; 6046e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CovariantThunks_t CovariantThunks; 60515a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump std::vector<Index_t> VCalls; 606552b275708a25aa1d939b2b77e5419a0b4b8e6d4Mike Stump typedef CXXRecordDecl::method_iterator method_iter; 607ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump // FIXME: Linkage should follow vtable 608ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump const bool Extern; 60977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump const uint32_t LLVMPointerWidth; 61077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t extra; 6117c435fa7f7666b22abbe8494c537ebc25209223dMike Stumppublic: 612eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump VtableBuilder(std::vector<llvm::Constant *> &meth, 613eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump const CXXRecordDecl *c, 614eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump CodeGenModule &cgm) 615b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump : methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)), 616b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()), 61777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump CGM(cgm), Extern(true), 61877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { 6197c435fa7f7666b22abbe8494c537ebc25209223dMike Stump Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 6207c435fa7f7666b22abbe8494c537ebc25209223dMike Stump } 62132f3701853a8237704065c77abc17369dd02c39bMike Stump 622f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; } 62397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex() 62497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump { return VBIndex; } 625b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump 62615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::Constant *wrap(Index_t i) { 6277c435fa7f7666b22abbe8494c537ebc25209223dMike Stump llvm::Constant *m; 62815a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i); 62915a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); 63015a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 6317c435fa7f7666b22abbe8494c537ebc25209223dMike Stump 63215a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::Constant *wrap(llvm::Constant *m) { 63315a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump return llvm::ConstantExpr::getBitCast(m, Ptr8Ty); 63480a0e32d60e4ff7d78f411e73f3e8dea769ed313Mike Stump } 6354c3aedd3f1fff57d1906b0cdfa7a9ec81a361b2dMike Stump 6367fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets, 637b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump const CXXRecordDecl *RD, uint64_t Offset) { 63897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 6397fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump e = RD->bases_end(); i != e; ++i) { 6401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 6417fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 6427fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump if (i->isVirtual() && !SeenVBase.count(Base)) { 6437fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump SeenVBase.insert(Base); 644b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8; 64515a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::Constant *m = wrap(BaseOffset); 64615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump m = wrap((0?700:0) + BaseOffset); 64797f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump VBIndex[Base] = -(offsets.size()*LLVMPointerWidth/8) 64897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump - 3*LLVMPointerWidth/8; 6497fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump offsets.push_back(m); 6507fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump } 651b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump GenerateVBaseOffsets(offsets, Base, Offset); 6527fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump } 6537fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump } 6547fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump 655b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump void StartNewTable() { 656b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump SeenVBase.clear(); 657b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump } 65865defe3ee7be121aef50b498e51f1d831b4a15f3Mike Stump 65997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B); 66097f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 66197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump /// getVbaseOffset - Returns the index into the vtable for the virtual base 66297f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump /// offset for the given (B) virtual base of the derived class D. 66397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump Index_t getVbaseOffset(QualType qB, QualType qD) { 66497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump qD = qD->getAs<PointerType>()->getPointeeType(); 66597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump qB = qB->getAs<PointerType>()->getPointeeType(); 66697f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl()); 66797f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl()); 66897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump if (D != Class) 66997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump return VBlookup(D, B); 67097f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i; 67197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump i = VBIndex.find(B); 67297f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump if (i != VBIndex.end()) 67397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump return i->second; 67497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // FIXME: temporal botch, is this data here, by the time we need it? 67597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 67697f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // FIXME: Locate the containing virtual base first. 67797f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump return 42; 67897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump } 67997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 68035191b61db617aefba43b8add88a2ec88af67592Mike Stump bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m, 681dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump bool MorallyVirtual, Index_t Offset) { 682b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump typedef CXXMethodDecl::method_iterator meth_iter; 683b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 684b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // FIXME: Don't like the nested loops. For very large inheritance 685b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // heirarchies we could have a table on the side with the final overridder 686b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // and just replace each instance of an overridden method once. Would be 687b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // nice to measure the cost/benefit on real code. 688b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 689b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump for (meth_iter mi = MD->begin_overridden_methods(), 690b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump e = MD->end_overridden_methods(); 691b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump mi != e; ++mi) { 692b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump const CXXMethodDecl *OMD = *mi; 693b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump llvm::Constant *om; 694555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson om = CGM.GetAddrOfFunction(OMD, Ptr8Ty); 695b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty); 696b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 697dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump for (Index_t i = 0, e = submethods.size(); 698f0070dbae9535836ad41711081465dec2259786bMike Stump i != e; ++i) { 699b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // FIXME: begin_overridden_methods might be too lax, covariance */ 70077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (submethods[i] != om) 70177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump continue; 702183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall QualType nc_oret = OMD->getType()->getAs<FunctionType>()->getResultType(); 7036e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CanQualType oret = CGM.getContext().getCanonicalType(nc_oret); 704183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType(); 7056e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CanQualType ret = CGM.getContext().getCanonicalType(nc_ret); 7066e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CallOffset ReturnOffset = std::make_pair(0, 0); 7076e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump if (oret != ret) { 7086e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // FIXME: calculate offsets for covariance 70997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump ReturnOffset = std::make_pair(42,getVbaseOffset(oret, ret)); 7106e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump } 711dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump Index[MD] = i; 71277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump submethods[i] = m; 71377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump 71477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks.erase(OMD); 71577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (MorallyVirtual) { 71677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t &idx = VCall[OMD]; 71777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (idx == 0) { 718dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump VCallOffset[MD] = Offset/8; 71977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump idx = VCalls.size()+1; 72077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump VCalls.push_back(0); 721dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump } else { 722dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump VCallOffset[MD] = VCallOffset[OMD]; 723dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump VCalls[idx-1] = -VCallOffset[OMD] + Offset/8; 72415a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 72577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump VCall[MD] = idx; 7266e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CallOffset ThisOffset; 7276e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // FIXME: calculate non-virtual offset 7286e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8)); 7296e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump if (ReturnOffset.first || ReturnOffset.second) 7306e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CovariantThunks[MD] = std::make_pair(ThisOffset, ReturnOffset); 7316e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump else 7326e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Thunks[MD] = ThisOffset; 73335191b61db617aefba43b8add88a2ec88af67592Mike Stump return true; 734b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump } 73577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump#if 0 73677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump // FIXME: finish off 73777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t O = VCallOffset[OMD] - Offset/8; 73877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (O) { 73977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks[MD] = std::make_pair(O, 0); 74077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 74177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump#endif 74277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump return true; 74365defe3ee7be121aef50b498e51f1d831b4a15f3Mike Stump } 744bc16aeab78748cca01a9d84fff71dd1109633ecdMike Stump } 745b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 74635191b61db617aefba43b8add88a2ec88af67592Mike Stump return false; 74735191b61db617aefba43b8add88a2ec88af67592Mike Stump } 74835191b61db617aefba43b8add88a2ec88af67592Mike Stump 74998cc71003d385561224e3711cd34c5b03f27ccdcMike Stump void InstallThunks() { 75077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end(); 75177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump i != e; ++i) { 75277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump const CXXMethodDecl *MD = i->first; 75377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t idx = Index[MD]; 75477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t nv_O = i->second.first; 75577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t v_O = i->second.second; 75698cc71003d385561224e3711cd34c5b03f27ccdcMike Stump submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O); 75777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 75877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks.clear(); 7596e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump for (CovariantThunks_t::iterator i = CovariantThunks.begin(), 7606e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump e = CovariantThunks.end(); 7616e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump i != e; ++i) { 7626e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump const CXXMethodDecl *MD = i->first; 7636e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t idx = Index[MD]; 7646e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t nv_t = i->second.first.first; 7656e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t v_t = i->second.first.second; 7666e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t nv_r = i->second.second.first; 7676e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t v_r = i->second.second.second; 7686e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r, 7696e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump v_r); 7706e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump } 7716e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CovariantThunks.clear(); 77277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 77377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump 774dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump void OverrideMethods(std::vector<std::pair<const CXXRecordDecl *, 775dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > *Path, bool MorallyVirtual) { 776dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump for (std::vector<std::pair<const CXXRecordDecl *, 777dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> >::reverse_iterator i =Path->rbegin(), 77898cc71003d385561224e3711cd34c5b03f27ccdcMike Stump e = Path->rend(); i != e; ++i) { 779dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump const CXXRecordDecl *RD = i->first; 780dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t Offset = i->second; 78198cc71003d385561224e3711cd34c5b03f27ccdcMike Stump for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; 78298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump ++mi) 78398cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (mi->isVirtual()) { 78498cc71003d385561224e3711cd34c5b03f27ccdcMike Stump const CXXMethodDecl *MD = *mi; 785c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson llvm::Constant *m = wrap(CGM.GetAddrOfFunction(MD)); 786dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump OverrideMethod(MD, m, MorallyVirtual, Offset); 78798cc71003d385561224e3711cd34c5b03f27ccdcMike Stump } 78898cc71003d385561224e3711cd34c5b03f27ccdcMike Stump } 789f9a883c27e3b5724a5a59499691fa109eb5032f8Mike Stump } 790f9a883c27e3b5724a5a59499691fa109eb5032f8Mike Stump 7916d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset) { 792c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson llvm::Constant *m = 0; 7933fec4c605e0dd074422bca21626c036f52dab31dAnders Carlsson if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) 794c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete)); 7953fec4c605e0dd074422bca21626c036f52dab31dAnders Carlsson else 796c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson m = wrap(CGM.GetAddrOfFunction(MD)); 7973fec4c605e0dd074422bca21626c036f52dab31dAnders Carlsson 79877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump // If we can find a previously allocated slot for this, reuse it. 799dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump if (OverrideMethod(MD, m, MorallyVirtual, Offset)) 80035191b61db617aefba43b8add88a2ec88af67592Mike Stump return; 8011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 802b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // else allocate a new slot. 80315a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump Index[MD] = submethods.size(); 804dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump submethods.push_back(m); 80515a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump if (MorallyVirtual) { 80615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump VCallOffset[MD] = Offset/8; 80715a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump Index_t &idx = VCall[MD]; 80815a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump // Allocate the first one, after that, we reuse the previous one. 80915a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump if (idx == 0) { 81015a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump idx = VCalls.size()+1; 81115a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump VCalls.push_back(0); 81215a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 81315a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 814b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump } 815b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 8166d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual, 8176d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump Index_t Offset) { 818b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; 819b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump ++mi) 820b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump if (mi->isVirtual()) 8216d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump AddMethod(*mi, MorallyVirtual, Offset); 822bc16aeab78748cca01a9d84fff71dd1109633ecdMike Stump } 823bc16aeab78748cca01a9d84fff71dd1109633ecdMike Stump 82477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout, 82577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump const CXXRecordDecl *PrimaryBase, 82677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump bool PrimaryBaseWasVirtual, bool MorallyVirtual, 82777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t Offset) { 82877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 82977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump e = RD->bases_end(); i != e; ++i) { 83077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (i->isVirtual()) 83177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump continue; 8321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 83377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 83477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (Base != PrimaryBase || PrimaryBaseWasVirtual) { 83577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump uint64_t o = Offset + Layout.getBaseClassOffset(Base); 83677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump StartNewTable(); 837dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump std::vector<std::pair<const CXXRecordDecl *, 838dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > S; 839dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump S.push_back(std::make_pair(RD, Offset)); 84098cc71003d385561224e3711cd34c5b03f27ccdcMike Stump GenerateVtableForBase(Base, MorallyVirtual, o, false, &S); 84177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 84277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 84377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 84477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump 8456d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets, 8466d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump const ASTRecordLayout &Layout, 8476d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump const CXXRecordDecl *PrimaryBase, 8486d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump bool PrimaryBaseWasVirtual, bool MorallyVirtual, 8496d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump int64_t Offset, bool ForVirtualBase) { 8506d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump StartNewTable(); 8516d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump extra = 0; 8526d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // FIXME: Cleanup. 8536d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump if (!ForVirtualBase) { 8546d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // then virtual base offsets... 8556d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), 8566d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump e = offsets.rend(); i != e; ++i) 8576d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(*i); 8586d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump } 8596d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 8606d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // The vcalls come first... 861dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump for (std::vector<Index_t>::reverse_iterator i=VCalls.rbegin(), 862dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump e=VCalls.rend(); 863dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump i != e; ++i) 8646d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(wrap((0?600:0) + *i)); 8656d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump VCalls.clear(); 8666d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 8676d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump if (ForVirtualBase) { 8686d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // then virtual base offsets... 8696d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), 8706d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump e = offsets.rend(); i != e; ++i) 8716d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(*i); 8726d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump } 8736d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 8746d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(wrap(-(Offset/8))); 8756d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(rtti); 8766d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump Index_t AddressPoint = methods.size(); 8776d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 87898cc71003d385561224e3711cd34c5b03f27ccdcMike Stump InstallThunks(); 8796d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.insert(methods.end(), submethods.begin(), submethods.end()); 8806d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump submethods.clear(); 8816d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 8826d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // and then the non-virtual bases. 8836d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, 8846d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump MorallyVirtual, Offset); 8856d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump return AddressPoint; 8866d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump } 8876d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 888078d778d8ea4a3975a985da4e8aaef2d269c82faMike Stump void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset) { 8899bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump if (!RD->isDynamicClass()) 8909bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump return; 8919bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 8929bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); 8931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); 8949bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); 8959bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 8969bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump // vtables are composed from the chain of primaries. 8979bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump if (PrimaryBase) { 8989bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump if (PrimaryBaseWasVirtual) 8999bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump IndirectPrimary.insert(PrimaryBase); 900078d778d8ea4a3975a985da4e8aaef2d269c82faMike Stump Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset); 9019bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump } 9029bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 9039bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump // And add the virtuals for the class to the primary vtable. 9049bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump AddMethods(RD, MorallyVirtual, Offset); 9059bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump } 9069bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 907e45c90f53e3fcb59a48e88862aa5cf5f5538556cMike Stump int64_t GenerateVtableForBase(const CXXRecordDecl *RD, 908a18df0ec71c5c95fb6809d4a80050f7b218f38b5Mike Stump bool MorallyVirtual = false, int64_t Offset = 0, 909a18df0ec71c5c95fb6809d4a80050f7b218f38b5Mike Stump bool ForVirtualBase = false, 910dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump std::vector<std::pair<const CXXRecordDecl *, 911dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > *Path = 0) { 912bf595a3b1f1737eb60203856ea34b759c4c09c46Mike Stump if (!RD->isDynamicClass()) 913263b3522add846130ff5f0a85568234e612a81caMike Stump return 0; 914109b13db3391face0b393c730f0326ca51d25b52Mike Stump 915109b13db3391face0b393c730f0326ca51d25b52Mike Stump const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); 9161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); 917109b13db3391face0b393c730f0326ca51d25b52Mike Stump const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); 918109b13db3391face0b393c730f0326ca51d25b52Mike Stump 91915a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump std::vector<llvm::Constant *> offsets; 920b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump extra = 0; 921b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump GenerateVBaseOffsets(offsets, RD, Offset); 922b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump if (ForVirtualBase) 923b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump extra = offsets.size(); 92402cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump 925109b13db3391face0b393c730f0326ca51d25b52Mike Stump // vtables are composed from the chain of primaries. 926109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (PrimaryBase) { 927109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (PrimaryBaseWasVirtual) 928109b13db3391face0b393c730f0326ca51d25b52Mike Stump IndirectPrimary.insert(PrimaryBase); 929078d778d8ea4a3975a985da4e8aaef2d269c82faMike Stump Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset); 930109b13db3391face0b393c730f0326ca51d25b52Mike Stump } 931276b9f1d814f4f6551cc3000590759a34185d6daMike Stump 93215a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump // And add the virtuals for the class to the primary vtable. 9336d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump AddMethods(RD, MorallyVirtual, Offset); 93415a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump 93598cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (Path) 936dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump OverrideMethods(Path, MorallyVirtual); 93798cc71003d385561224e3711cd34c5b03f27ccdcMike Stump 9386d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual, 9396d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump MorallyVirtual, Offset, ForVirtualBase); 940276b9f1d814f4f6551cc3000590759a34185d6daMike Stump } 941276b9f1d814f4f6551cc3000590759a34185d6daMike Stump 94298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump void GenerateVtableForVBases(const CXXRecordDecl *RD, 943dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t Offset = 0, 944dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump std::vector<std::pair<const CXXRecordDecl *, 945dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > *Path = 0) { 94698cc71003d385561224e3711cd34c5b03f27ccdcMike Stump bool alloc = false; 94798cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (Path == 0) { 94898cc71003d385561224e3711cd34c5b03f27ccdcMike Stump alloc = true; 949dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump Path = new std::vector<std::pair<const CXXRecordDecl *, 950dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> >; 95198cc71003d385561224e3711cd34c5b03f27ccdcMike Stump } 95298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump // FIXME: We also need to override using all paths to a virtual base, 95398cc71003d385561224e3711cd34c5b03f27ccdcMike Stump // right now, we just process the first path 954dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump Path->push_back(std::make_pair(RD, Offset)); 955109b13db3391face0b393c730f0326ca51d25b52Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 956109b13db3391face0b393c730f0326ca51d25b52Mike Stump e = RD->bases_end(); i != e; ++i) { 9571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 958109b13db3391face0b393c730f0326ca51d25b52Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 959109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (i->isVirtual() && !IndirectPrimary.count(Base)) { 960109b13db3391face0b393c730f0326ca51d25b52Mike Stump // Mark it so we don't output it twice. 961109b13db3391face0b393c730f0326ca51d25b52Mike Stump IndirectPrimary.insert(Base); 962b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump StartNewTable(); 963b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump int64_t BaseOffset = BLayout.getVBaseClassOffset(Base); 96498cc71003d385561224e3711cd34c5b03f27ccdcMike Stump GenerateVtableForBase(Base, true, BaseOffset, true, Path); 965109b13db3391face0b393c730f0326ca51d25b52Mike Stump } 966dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t BaseOffset = Offset; 967dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump if (i->isVirtual()) 968dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump BaseOffset = BLayout.getVBaseClassOffset(Base); 969109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (Base->getNumVBases()) 970dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump GenerateVtableForVBases(Base, BaseOffset, Path); 971109b13db3391face0b393c730f0326ca51d25b52Mike Stump } 97298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump Path->pop_back(); 97398cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (alloc) 97498cc71003d385561224e3711cd34c5b03f27ccdcMike Stump delete Path; 975e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump } 976109b13db3391face0b393c730f0326ca51d25b52Mike Stump}; 9778a12b564923a72224730a467007e61b5701e4aa7Mike Stump 978f0070dbae9535836ad41711081465dec2259786bMike Stumpclass VtableInfo { 979f0070dbae9535836ad41711081465dec2259786bMike Stumppublic: 980f0070dbae9535836ad41711081465dec2259786bMike Stump typedef VtableBuilder::Index_t Index_t; 981f0070dbae9535836ad41711081465dec2259786bMike Stumpprivate: 982f0070dbae9535836ad41711081465dec2259786bMike Stump CodeGenModule &CGM; // Per-module state. 983f0070dbae9535836ad41711081465dec2259786bMike Stump /// Index_t - Vtable index type. 984f0070dbae9535836ad41711081465dec2259786bMike Stump typedef llvm::DenseMap<const CXXMethodDecl *, Index_t> ElTy; 985f0070dbae9535836ad41711081465dec2259786bMike Stump typedef llvm::DenseMap<const CXXRecordDecl *, ElTy *> MapTy; 986f0070dbae9535836ad41711081465dec2259786bMike Stump // FIXME: Move to Context. 987f0070dbae9535836ad41711081465dec2259786bMike Stump static MapTy IndexFor; 98897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 98997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump typedef llvm::DenseMap<const CXXRecordDecl *, Index_t> VBElTy; 99097f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump typedef llvm::DenseMap<const CXXRecordDecl *, VBElTy *> VBMapTy; 99197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // FIXME: Move to Context. 99297f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump static VBMapTy VBIndexFor; 993f0070dbae9535836ad41711081465dec2259786bMike Stumppublic: 994f0070dbae9535836ad41711081465dec2259786bMike Stump VtableInfo(CodeGenModule &cgm) : CGM(cgm) { } 99597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump void RegisterIndex(const CXXRecordDecl *RD, const ElTy &e) { 996f0070dbae9535836ad41711081465dec2259786bMike Stump assert(IndexFor.find(RD) == IndexFor.end() && "Don't compute vtbl twice"); 997f0070dbae9535836ad41711081465dec2259786bMike Stump // We own a copy of this, it will go away shortly. 998f0070dbae9535836ad41711081465dec2259786bMike Stump IndexFor[RD] = new ElTy (e); 999f0070dbae9535836ad41711081465dec2259786bMike Stump } 100097f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump void RegisterVBIndex(const CXXRecordDecl *RD, const VBElTy &e) { 100197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump assert(VBIndexFor.find(RD) == VBIndexFor.end() && "Don't compute vtbl twice"); 100297f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // We own a copy of this, it will go away shortly. 100397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump VBIndexFor[RD] = new VBElTy (e); 100497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump } 1005f0070dbae9535836ad41711081465dec2259786bMike Stump Index_t lookup(const CXXMethodDecl *MD) { 1006f0070dbae9535836ad41711081465dec2259786bMike Stump const CXXRecordDecl *RD = MD->getParent(); 1007f0070dbae9535836ad41711081465dec2259786bMike Stump MapTy::iterator I = IndexFor.find(RD); 1008f0070dbae9535836ad41711081465dec2259786bMike Stump if (I == IndexFor.end()) { 1009f0070dbae9535836ad41711081465dec2259786bMike Stump std::vector<llvm::Constant *> methods; 101097f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // FIXME: This seems expensive. Can we do a partial job to get 101197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // just this data. 1012f0070dbae9535836ad41711081465dec2259786bMike Stump VtableBuilder b(methods, RD, CGM); 1013a18df0ec71c5c95fb6809d4a80050f7b218f38b5Mike Stump b.GenerateVtableForBase(RD); 1014bf595a3b1f1737eb60203856ea34b759c4c09c46Mike Stump b.GenerateVtableForVBases(RD); 101597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump RegisterIndex(RD, b.getIndex()); 1016f0070dbae9535836ad41711081465dec2259786bMike Stump I = IndexFor.find(RD); 1017f0070dbae9535836ad41711081465dec2259786bMike Stump } 1018f0070dbae9535836ad41711081465dec2259786bMike Stump assert(I->second->find(MD)!=I->second->end() && "Can't find vtable index"); 1019f0070dbae9535836ad41711081465dec2259786bMike Stump return (*I->second)[MD]; 1020f0070dbae9535836ad41711081465dec2259786bMike Stump } 102197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump Index_t VBlookup(const CXXRecordDecl *RD, const CXXRecordDecl *BD) { 102297f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump VBMapTy::iterator I = VBIndexFor.find(RD); 102397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump if (I == VBIndexFor.end()) { 102497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump std::vector<llvm::Constant *> methods; 102597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // FIXME: This seems expensive. Can we do a partial job to get 102697f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump // just this data. 102797f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump VtableBuilder b(methods, RD, CGM); 102897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump b.GenerateVtableForBase(RD); 102997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump b.GenerateVtableForVBases(RD); 103097f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump RegisterVBIndex(RD, b.getVBIndex()); 103197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump I = VBIndexFor.find(RD); 103297f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump } 103397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump assert(I->second->find(BD)!=I->second->end() && "Can't find vtable index"); 103497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump return (*I->second)[BD]; 103597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump } 1036f0070dbae9535836ad41711081465dec2259786bMike Stump}; 1037f0070dbae9535836ad41711081465dec2259786bMike Stump 103897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump// FIXME: move to Context 103997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stumpstatic VtableInfo *vtableinfo; 104097f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 104197f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike StumpVtableBuilder::Index_t VtableBuilder::VBlookup(CXXRecordDecl *D, 104297f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump CXXRecordDecl *B) { 104397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump if (vtableinfo == 0) 104497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump vtableinfo = new VtableInfo(CGM); 104597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 104697f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump return vtableinfo->VBlookup(D, B); 104797f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump} 104897f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 104997f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 1050f0070dbae9535836ad41711081465dec2259786bMike Stump// FIXME: Move to Context. 1051f0070dbae9535836ad41711081465dec2259786bMike StumpVtableInfo::MapTy VtableInfo::IndexFor; 1052f0070dbae9535836ad41711081465dec2259786bMike Stump 105397f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump// FIXME: Move to Context. 105497f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike StumpVtableInfo::VBMapTy VtableInfo::VBIndexFor; 105597f4d46e2fffa1e8a84f2052c314a3bf87b967f8Mike Stump 1056f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stumpllvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { 1057f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::SmallString<256> OutName; 1058f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::raw_svector_ostream Out(OutName); 1059f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump QualType ClassTy; 1060e607ed068334bacb8d7b093996b4671c6ca79e25Mike Stump ClassTy = getContext().getTagDeclType(RD); 1061f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump mangleCXXVtable(ClassTy, getContext(), Out); 106282b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::GlobalVariable::LinkageTypes linktype; 106382b56961dcb813674dbda3c5f5aaee703d55741cMike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 106482b56961dcb813674dbda3c5f5aaee703d55741cMike Stump std::vector<llvm::Constant *> methods; 1065276b9f1d814f4f6551cc3000590759a34185d6daMike Stump llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 106698cc71003d385561224e3711cd34c5b03f27ccdcMike Stump int64_t AddressPoint; 10676f376336138ea719e3c4757ae046a5768043b276Mike Stump 1068eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump VtableBuilder b(methods, RD, CGM); 1069109b13db3391face0b393c730f0326ca51d25b52Mike Stump 1070276b9f1d814f4f6551cc3000590759a34185d6daMike Stump // First comes the vtables for all the non-virtual bases... 107198cc71003d385561224e3711cd34c5b03f27ccdcMike Stump AddressPoint = b.GenerateVtableForBase(RD); 107270101ce87ff1d73ac90e4d99a3af0ae509e5934fMike Stump 1073276b9f1d814f4f6551cc3000590759a34185d6daMike Stump // then the vtables for all the virtual bases. 1074bf595a3b1f1737eb60203856ea34b759c4c09c46Mike Stump b.GenerateVtableForVBases(RD); 10756f376336138ea719e3c4757ae046a5768043b276Mike Stump 107682b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::Constant *C; 107782b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size()); 107882b56961dcb813674dbda3c5f5aaee703d55741cMike Stump C = llvm::ConstantArray::get(type, methods); 107982b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::Value *vtable = new llvm::GlobalVariable(CGM.getModule(), type, true, 10807765934ad7e157b5fcf925792a38e01b1edbcf8aDaniel Dunbar linktype, C, Out.str()); 1081f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump vtable = Builder.CreateBitCast(vtable, Ptr8Ty); 1082f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump vtable = Builder.CreateGEP(vtable, 1083276b9f1d814f4f6551cc3000590759a34185d6daMike Stump llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 108498cc71003d385561224e3711cd34c5b03f27ccdcMike Stump AddressPoint*LLVMPointerWidth/8)); 1085f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump return vtable; 1086f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump} 1087f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump 1088ed032eb5c18b99528cbd76415337b6056a72b911Mike Stumpllvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn, 1089ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump const CXXMethodDecl *MD, 109077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump bool Extern, int64_t nv, 109177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t v) { 1092183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall QualType R = MD->getType()->getAs<FunctionType>()->getResultType(); 1093ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 1094ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FunctionArgList Args; 1095ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ImplicitParamDecl *ThisDecl = 1096ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 1097ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump MD->getThisType(getContext())); 1098ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); 1099ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump for (FunctionDecl::param_const_iterator i = MD->param_begin(), 1100ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump e = MD->param_end(); 1101ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump i != e; ++i) { 1102ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ParmVarDecl *D = *i; 1103ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump Args.push_back(std::make_pair(D, D->getType())); 1104ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump } 1105ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump IdentifierInfo *II 1106ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump = &CGM.getContext().Idents.get("__thunk_named_foo_"); 1107ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FunctionDecl *FD = FunctionDecl::Create(getContext(), 1108ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump getContext().getTranslationUnitDecl(), 1109ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump SourceLocation(), II, R, 0, 1110ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump Extern 1111ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ? FunctionDecl::Extern 1112ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump : FunctionDecl::Static, 1113ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump false, true); 1114ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump StartFunction(FD, R, Fn, Args, SourceLocation()); 1115ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump // FIXME: generate body 1116ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FinishFunction(); 1117ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump return Fn; 1118ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump} 1119ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 11206e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stumpllvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, 11216e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump const CXXMethodDecl *MD, 11226e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump bool Extern, 11236e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t nv_t, 11246e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_t, 11256e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t nv_r, 11266e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_r) { 1127183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall QualType R = MD->getType()->getAs<FunctionType>()->getResultType(); 11286e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 11296e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FunctionArgList Args; 11306e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ImplicitParamDecl *ThisDecl = 11316e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 11326e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump MD->getThisType(getContext())); 11336e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); 11346e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump for (FunctionDecl::param_const_iterator i = MD->param_begin(), 11356e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump e = MD->param_end(); 11366e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump i != e; ++i) { 11376e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ParmVarDecl *D = *i; 11386e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Args.push_back(std::make_pair(D, D->getType())); 11396e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump } 11406e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump IdentifierInfo *II 11416e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump = &CGM.getContext().Idents.get("__thunk_named_foo_"); 11426e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FunctionDecl *FD = FunctionDecl::Create(getContext(), 11436e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump getContext().getTranslationUnitDecl(), 11446e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump SourceLocation(), II, R, 0, 11456e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Extern 11466e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ? FunctionDecl::Extern 11476e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump : FunctionDecl::Static, 11486e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump false, true); 11496e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump StartFunction(FD, R, Fn, Args, SourceLocation()); 11506e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // FIXME: generate body 11516e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FinishFunction(); 11526e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump return Fn; 11536e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump} 11546e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 115577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stumpllvm::Constant *CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern, 115677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t nv, int64_t v) { 1157ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::SmallString<256> OutName; 1158ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::raw_svector_ostream Out(OutName); 115977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump mangleThunk(MD, nv, v, getContext(), Out); 1160ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::GlobalVariable::LinkageTypes linktype; 1161ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 1162ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump if (!Extern) 1163ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump linktype = llvm::GlobalValue::InternalLinkage; 1164ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 1165183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 1166ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump const llvm::FunctionType *FTy = 1167ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), 1168ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FPT->isVariadic()); 1169ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 1170ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(), 1171ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump &getModule()); 117277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump CodeGenFunction(*this).GenerateThunk(Fn, MD, Extern, nv, v); 1173ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump // Fn = Builder.CreateBitCast(Fn, Ptr8Ty); 1174ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); 1175ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump return m; 1176ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump} 1177ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 11786e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stumpllvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, 11796e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump bool Extern, int64_t nv_t, 11806e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_t, int64_t nv_r, 11816e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_r) { 11826e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::SmallString<256> OutName; 11836e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::raw_svector_ostream Out(OutName); 11846e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump mangleCovariantThunk(MD, nv_t, v_t, nv_r, v_r, getContext(), Out); 11856e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::GlobalVariable::LinkageTypes linktype; 11866e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 11876e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump if (!Extern) 11886e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump linktype = llvm::GlobalValue::InternalLinkage; 11896e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 1190183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 11916e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump const llvm::FunctionType *FTy = 11926e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), 11936e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FPT->isVariadic()); 11946e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 11956e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(), 11966e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump &getModule()); 11976e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r, 11986e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump v_r); 11996e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // Fn = Builder.CreateBitCast(Fn, Ptr8Ty); 12006e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); 12016e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump return m; 12026e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump} 12036e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 1204f0070dbae9535836ad41711081465dec2259786bMike Stumpllvm::Value * 1205f0070dbae9535836ad41711081465dec2259786bMike StumpCodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This, 1206f0070dbae9535836ad41711081465dec2259786bMike Stump const llvm::Type *Ty) { 1207f0070dbae9535836ad41711081465dec2259786bMike Stump // FIXME: If we know the dynamic type, we don't have to do a virtual dispatch. 12081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12092b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson uint64_t Index = CGM.GetVtableIndex(MD); 12102b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson 1211f0070dbae9535836ad41711081465dec2259786bMike Stump Ty = llvm::PointerType::get(Ty, 0); 1212f0070dbae9535836ad41711081465dec2259786bMike Stump Ty = llvm::PointerType::get(Ty, 0); 1213f0070dbae9535836ad41711081465dec2259786bMike Stump Ty = llvm::PointerType::get(Ty, 0); 1214f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::Value *vtbl = Builder.CreateBitCast(This, Ty); 1215f0070dbae9535836ad41711081465dec2259786bMike Stump vtbl = Builder.CreateLoad(vtbl); 1216f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::Value *vfn = Builder.CreateConstInBoundsGEP1_64(vtbl, 12172b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson Index, "vfn"); 1218f0070dbae9535836ad41711081465dec2259786bMike Stump vfn = Builder.CreateLoad(vfn); 1219f0070dbae9535836ad41711081465dec2259786bMike Stump return vfn; 1220f0070dbae9535836ad41711081465dec2259786bMike Stump} 1221f0070dbae9535836ad41711081465dec2259786bMike Stump 12222b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlssonuint64_t CodeGenModule::GetVtableIndex(const CXXMethodDecl *MD) { 12232b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson // FIXME: move to CodeGenModule. 12242b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson if (vtableinfo == 0) 12252b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson vtableinfo = new VtableInfo(*this); 12262b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson 12272b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson return vtableinfo->lookup(MD); 12282b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson} 12292b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson 1230eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class 1231eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// array of objects from SrcValue to DestValue. Copying can be either a bitwise 1232eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// copy or via a copy constructor call. 12334f68d537c3f072366b25f3137f052eee36fddfcdFariborz Jahanian// FIXME. Consolidate this with EmitCXXAggrConstructorCall. 12341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest, 1235eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *Src, 1236eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian const ArrayType *Array, 12371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *BaseClassDecl, 1238eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian QualType Ty) { 1239eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); 1240eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian assert(CA && "VLA cannot be copied over"); 1241eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor(); 12421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1243eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Create a temporary for the loop index and initialize it with 0. 1244eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), 1245eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian "loop.index"); 12461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* zeroConstant = 1247eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); 12482b3583573ba6b26b605aacaad9a50492fb3d6fe6Anders Carlsson Builder.CreateStore(zeroConstant, IndexPtr, false); 1249eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Start the loop with a block that tests the condition. 1250eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 1251eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 12521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1253eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(CondBlock); 12541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1255eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 1256eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Generate: if (loop-index < number-of-elements fall to the loop body, 1257eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // otherwise, go to the block after the for-loop. 1258eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian uint64_t NumElements = getContext().getConstantArrayElementCount(CA); 12591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value * NumElementsPtr = 1260eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); 1261eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 12621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, 1263eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian "isless"); 1264eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // If the condition is true, execute the body. 1265eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateCondBr(IsLess, ForBody, AfterFor); 12661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1267eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(ForBody); 1268eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 1269eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Inside the loop body, emit the constructor call on the array element. 1270eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1271eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); 1272eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); 1273eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian if (BitwiseCopy) 1274eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 12751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (CXXConstructorDecl *BaseCopyCtor = 1276eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BaseClassDecl->getCopyConstructor(getContext(), 0)) { 12771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, 1278eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Ctor_Complete); 1279eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian CallArgList CallArgs; 1280eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Push the this (Dest) ptr. 1281eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1282eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BaseCopyCtor->getThisType(getContext()))); 12831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1284eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Push the Src ptr. 1285eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1286eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BaseCopyCtor->getParamDecl(0)->getType())); 12871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType ResultType = 1288183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); 1289eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1290eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Callee, CallArgs, BaseCopyCtor); 1291eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian } 1292eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(ContinueBlock); 12931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1294eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Emit the increment of the loop counter. 1295eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); 1296eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1297eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); 1298eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateStore(NextVal, IndexPtr, false); 12991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1300eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Finally, branch back up to the condition for the next iteration. 1301eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBranch(CondBlock); 13021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1303eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Emit the fall-through block. 1304eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(AfterFor, true); 1305eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian} 1306eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian 1307c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian/// EmitClassAggrCopyAssignment - This routine generates code to assign a class 13081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// array of objects from SrcValue to DestValue. Assignment can be either a 1309c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian/// bitwise assignment or via a copy assignment operator function call. 1310c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian/// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy 13111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest, 1312c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *Src, 1313c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const ArrayType *Array, 13141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *BaseClassDecl, 1315c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian QualType Ty) { 1316c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); 1317c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian assert(CA && "VLA cannot be asssigned"); 1318c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment(); 13191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1320c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Create a temporary for the loop index and initialize it with 0. 1321c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), 1322c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian "loop.index"); 13231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* zeroConstant = 1324c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); 1325c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateStore(zeroConstant, IndexPtr, false); 1326c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Start the loop with a block that tests the condition. 1327c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 1328c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 13291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1330c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(CondBlock); 13311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1332c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 1333c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Generate: if (loop-index < number-of-elements fall to the loop body, 1334c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // otherwise, go to the block after the for-loop. 1335c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian uint64_t NumElements = getContext().getConstantArrayElementCount(CA); 13361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value * NumElementsPtr = 1337c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); 1338c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 13391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, 1340c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian "isless"); 1341c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // If the condition is true, execute the body. 1342c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateCondBr(IsLess, ForBody, AfterFor); 13431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1344c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(ForBody); 1345c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 1346c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Inside the loop body, emit the assignment operator call on array element. 1347c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1348c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); 1349c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); 1350c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const CXXMethodDecl *MD = 0; 1351c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian if (BitwiseAssign) 1352c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 1353c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian else { 1354c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(), 1355c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian MD); 1356c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign"); 1357c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian (void)hasCopyAssign; 1358183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 1359c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const llvm::Type *LTy = 1360c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 1361c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian FPT->isVariadic()); 1362555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); 13631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1364c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CallArgList CallArgs; 1365c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Push the this (Dest) ptr. 1366c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1367c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian MD->getThisType(getContext()))); 13681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1369c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Push the Src ptr. 1370c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1371c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian MD->getParamDecl(0)->getType())); 1372183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); 1373c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1374c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Callee, CallArgs, MD); 1375c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian } 1376c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(ContinueBlock); 13771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1378c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Emit the increment of the loop counter. 1379c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); 1380c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1381c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); 1382c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateStore(NextVal, IndexPtr, false); 13831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1384c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Finally, branch back up to the condition for the next iteration. 1385c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBranch(CondBlock); 13861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1387c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Emit the fall-through block. 1388c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(AfterFor, true); 1389c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian} 1390c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian 1391ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian/// EmitClassMemberwiseCopy - This routine generates code to copy a class 1392ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian/// object from SrcValue to DestValue. Copying can be either a bitwise copy 1393eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// or via a copy constructor call. 1394ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanianvoid CodeGenFunction::EmitClassMemberwiseCopy( 1395942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian llvm::Value *Dest, llvm::Value *Src, 13961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *ClassDecl, 1397942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian const CXXRecordDecl *BaseClassDecl, QualType Ty) { 1398942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian if (ClassDecl) { 13995a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Dest = GetAddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl, 14005a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 14015a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Src = GetAddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl, 14025a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 1403942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian } 1404942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian if (BaseClassDecl->hasTrivialCopyConstructor()) { 1405942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 1406ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian return; 1407942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian } 14081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (CXXConstructorDecl *BaseCopyCtor = 141080e4b9e0e87064a824d72b6ff89074206ecced58Fariborz Jahanian BaseClassDecl->getCopyConstructor(getContext(), 0)) { 14111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, 1412ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian Ctor_Complete); 1413ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgList CallArgs; 1414ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian // Push the this (Dest) ptr. 1415ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1416ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian BaseCopyCtor->getThisType(getContext()))); 14171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1418ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian // Push the Src ptr. 1419ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1420370c884d172329384973e452647fba0b2f5146d5Fariborz Jahanian BaseCopyCtor->getParamDecl(0)->getType())); 14211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType ResultType = 1422183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall BaseCopyCtor->getType()->getAs<FunctionType>()->getResultType(); 1423ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1424ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian Callee, CallArgs, BaseCopyCtor); 1425ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian } 1426ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian} 142706f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian 14280270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// EmitClassCopyAssignment - This routine generates code to copy assign a class 14291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// object from SrcValue to DestValue. Assignment can be either a bitwise 14300270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// assignment of via an assignment operator call. 1431c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian// FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot. 14320270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanianvoid CodeGenFunction::EmitClassCopyAssignment( 14330270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *Dest, llvm::Value *Src, 14341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *ClassDecl, 14351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *BaseClassDecl, 14360270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian QualType Ty) { 14370270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (ClassDecl) { 14385a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Dest = GetAddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl, 14395a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 14405a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Src = GetAddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl, 14415a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 14420270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 14430270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (BaseClassDecl->hasTrivialCopyAssignment()) { 14440270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 14450270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian return; 14460270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 14471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14480270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const CXXMethodDecl *MD = 0; 14491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump bool ConstCopyAssignOp = BaseClassDecl->hasConstCopyAssignment(getContext(), 1450e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian MD); 1451e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian assert(ConstCopyAssignOp && "EmitClassCopyAssignment - missing copy assign"); 1452e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian (void)ConstCopyAssignOp; 1453e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian 1454183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 14551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *LTy = 14561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 1457e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian FPT->isVariadic()); 1458555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); 14591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1460e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian CallArgList CallArgs; 1461e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian // Push the this (Dest) ptr. 1462e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1463e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian MD->getThisType(getContext()))); 14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1465e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian // Push the Src ptr. 1466e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1467e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian MD->getParamDecl(0)->getType())); 14681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType ResultType = 1469183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall MD->getType()->getAs<FunctionType>()->getResultType(); 1470e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1471e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian Callee, CallArgs, MD); 14720270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian} 14730270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian 147406f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian/// SynthesizeDefaultConstructor - synthesize a default constructor 14751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 1476de1d26b9c1d8823b173e4d77015ad88b4da70559Anders CarlssonCodeGenFunction::SynthesizeDefaultConstructor(const CXXConstructorDecl *Ctor, 1477de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson CXXCtorType Type, 147806f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian llvm::Function *Fn, 147906f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian const FunctionArgList &Args) { 1480de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, 1481de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson SourceLocation()); 1482de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson EmitCtorPrologue(Ctor, Type); 148306f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian FinishFunction(); 148406f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian} 148506f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian 14868c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a copy 148797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// constructor, in accordance with section 12.8 (p7 and p8) of C++03 14881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// The implicitly-defined copy constructor for class X performs a memberwise 14891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// copy of its subobjects. The order of copying is the same as the order 149097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// of initialization of bases and members in a user-defined constructor 149197a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// Each subobject is copied in the manner appropriate to its type: 14921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of class type, the copy constructor for the class is 149397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// used; 14941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is an array, each element is copied, in the manner 149597a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// appropriate to the element type; 14961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of scalar type, the built-in assignment operator is 149797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// used. 14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// Virtual base class subobjects shall be copied only once by the 14991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// implicitly-defined copy constructor 150097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 1501de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlssonvoid 1502de1d26b9c1d8823b173e4d77015ad88b4da70559Anders CarlssonCodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *Ctor, 1503de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson CXXCtorType Type, 1504de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson llvm::Function *Fn, 1505de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson const FunctionArgList &Args) { 15060ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson const CXXRecordDecl *ClassDecl = Ctor->getParent(); 150797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyConstructor() && 15088c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian "SynthesizeCXXCopyConstructor - copy constructor has definition already"); 1509de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson StartFunction(GlobalDecl(Ctor, Type), Ctor->getResultType(), Fn, Args, 1510de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson SourceLocation()); 15111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15121e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian FunctionArgList::const_iterator i = Args.begin(); 15131e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian const VarDecl *ThisArg = i->first; 15141e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); 15151e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); 15161e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian const VarDecl *SrcArg = (i+1)->first; 15171e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); 15181e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); 15191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); 152197a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 152297a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian // FIXME. copy constrution of virtual base NYI 152397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian if (Base->isVirtual()) 152497a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian continue; 15251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152697a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian CXXRecordDecl *BaseClassDecl 152797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 1528942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, 1529942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian Base->getType()); 153097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian } 15311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15321e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 15331e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian FieldEnd = ClassDecl->field_end(); 15341e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian Field != FieldEnd; ++Field) { 15351e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 15361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1537eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1538eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian if (Array) 1539eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 15401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15411e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { 15421e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian CXXRecordDecl *FieldClassDecl 15431e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian = cast<CXXRecordDecl>(FieldClassType->getDecl()); 15441e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 15451e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 1546eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian if (Array) { 1547eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1548eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 15491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *DestBaseAddrPtr = 1550eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 15511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *SrcBaseAddrPtr = 1552eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateBitCast(RHS.getAddress(), BasePtr); 1553eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array, 1554eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian FieldClassDecl, FieldType); 1555eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian } 15561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 15571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), 1558eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian 0 /*ClassDecl*/, FieldClassDecl, FieldType); 15591e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian continue; 15601e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian } 1561f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian // Do a built-in assignment of scalar data members. 1562f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 1563f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 1564f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian RValue RVRHS = EmitLoadOfLValue(RHS, FieldType); 1565f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian EmitStoreThroughLValue(RVRHS, LHS, FieldType); 15661e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian } 15678c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian FinishFunction(); 15681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 156997a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 15702198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. 15711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// Before the implicitly-declared copy assignment operator for a class is 15721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// implicitly defined, all implicitly- declared copy assignment operators for 15731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// its direct base classes and its nonstatic data members shall have been 15742198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// implicitly defined. [12.8-p12] 15751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// The implicitly-defined copy assignment operator for class X performs 15761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// memberwise assignment of its subob- jects. The direct base classes of X are 15771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// assigned first, in the order of their declaration in 15781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// the base-specifier-list, and then the immediate nonstatic data members of X 15791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// are assigned, in the order in which they were declared in the class 15802198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// definition.Each subobject is assigned in the manner appropriate to its type: 15811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of class type, the copy assignment operator for the 15821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// class is used (as if by explicit qualification; that is, ignoring any 15832198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// possible virtual overriding functions in more derived classes); 15840270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// 15851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is an array, each element is assigned, in the manner 15862198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// appropriate to the element type; 15870270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// 15881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of scalar type, the built-in assignment operator is 15892198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// used. 15902198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanianvoid CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, 15912198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian llvm::Function *Fn, 15922198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian const FunctionArgList &Args) { 15930270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian 15940270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); 15950270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyAssignment() && 15960270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian "SynthesizeCXXCopyAssignment - copy assignment has user declaration"); 1597de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson StartFunction(CD, CD->getResultType(), Fn, Args, SourceLocation()); 15981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15990270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian FunctionArgList::const_iterator i = Args.begin(); 16000270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const VarDecl *ThisArg = i->first; 16010270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); 16020270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); 16030270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const VarDecl *SrcArg = (i+1)->first; 16040270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); 16050270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); 16061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16070270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); 16080270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 16090270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian // FIXME. copy assignment of virtual base NYI 16100270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (Base->isVirtual()) 16110270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian continue; 16121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16130270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian CXXRecordDecl *BaseClassDecl 16140270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 16150270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, 16160270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian Base->getType()); 16170270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 16181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16190270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 16200270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian FieldEnd = ClassDecl->field_end(); 16210270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian Field != FieldEnd; ++Field) { 16220270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 16231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1624c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1625c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian if (Array) 1626c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 16271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16280270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { 16290270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian CXXRecordDecl *FieldClassDecl 16300270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian = cast<CXXRecordDecl>(FieldClassType->getDecl()); 16310270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 16320270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 1633c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian if (Array) { 1634c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1635c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 1636c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *DestBaseAddrPtr = 1637c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 1638c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *SrcBaseAddrPtr = 1639c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateBitCast(RHS.getAddress(), BasePtr); 1640c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array, 1641c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian FieldClassDecl, FieldType); 1642c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian } 1643c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian else 16441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(), 1645c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian 0 /*ClassDecl*/, FieldClassDecl, FieldType); 16460270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian continue; 16470270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 16480270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian // Do a built-in assignment of scalar data members. 16490270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 16500270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 16510270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian RValue RVRHS = EmitLoadOfLValue(RHS, FieldType); 16520270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian EmitStoreThroughLValue(RVRHS, LHS, FieldType); 1653183d7181fd59842ac969cbc6fe0376f85dc63ae4Fariborz Jahanian } 16541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1655183d7181fd59842ac969cbc6fe0376f85dc63ae4Fariborz Jahanian // return *this; 1656183d7181fd59842ac969cbc6fe0376f85dc63ae4Fariborz Jahanian Builder.CreateStore(LoadOfThis, ReturnValue); 16571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16582198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian FinishFunction(); 16591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 166097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 1661e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian/// EmitCtorPrologue - This routine generates necessary code to initialize 1662e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian/// base classes and non-static data members belonging to this constructor. 1663174754cda4596f3bb2539df61ab2ab7a17aad6bfAnders Carlsson/// FIXME: This needs to take a CXXCtorType. 1664de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlssonvoid CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, 1665de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson CXXCtorType CtorType) { 1666742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); 1667eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump // FIXME: Add vbase initialization 1668f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *LoadOfThis = 0; 16691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1670742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), 1671e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian E = CD->init_end(); 1672e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian B != E; ++B) { 1673e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian CXXBaseOrMemberInitializer *Member = (*B); 1674e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian if (Member->isBaseInitializer()) { 1675f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 16766d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian Type *BaseType = Member->getBaseClass(); 16771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CXXRecordDecl *BaseClassDecl = 16786217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); 16795a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl, 16805a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson BaseClassDecl, 16815a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 1682742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian EmitCXXConstructorCall(Member->getConstructor(), 1683de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson CtorType, V, 16841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Member->const_arg_begin(), 1685742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian Member->const_arg_end()); 1686b3589f44c5d295cd41de2c83f3475116835eeebdMike Stump } else { 1687e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian // non-static data member initilaizers. 1688e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian FieldDecl *Field = Member->getMember(); 1689e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian QualType FieldType = getContext().getCanonicalType((Field)->getType()); 16901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1691eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 169264a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian if (Array) 169364a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 16941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1695f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 1696e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman LValue LHS; 1697e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman if (FieldType->isReferenceType()) { 1698e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman // FIXME: This is really ugly; should be refactored somehow 1699e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); 1700e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman llvm::Value *V = Builder.CreateStructGEP(LoadOfThis, idx, "tmp"); 17010953e767ff7817f97b3ab20896b229891eeff45bJohn McCall assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs"); 17020953e767ff7817f97b3ab20896b229891eeff45bJohn McCall LHS = LValue::MakeAddr(V, MakeQualifiers(FieldType)); 1703e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman } else { 1704e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman LHS = EmitLValueForField(LoadOfThis, Field, false, 0); 1705e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman } 17066217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (FieldType->getAs<RecordType>()) { 1707e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian if (!Field->isAnonymousStructOrUnion()) { 17081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(Member->getConstructor() && 170950b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian "EmitCtorPrologue - no constructor to initialize member"); 171064a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian if (Array) { 171164a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 171264a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 17131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 171464a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 17151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXAggrConstructorCall(Member->getConstructor(), 171664a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Array, BaseAddrPtr); 171764a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian } 171864a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian else 171964a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian EmitCXXConstructorCall(Member->getConstructor(), 172064a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Ctor_Complete, LHS.getAddress(), 17211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Member->const_arg_begin(), 172264a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Member->const_arg_end()); 1723e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian continue; 1724e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian } 1725e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian else { 1726e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian // Initializing an anonymous union data member. 1727e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian FieldDecl *anonMember = Member->getAnonUnionMember(); 17281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump LHS = EmitLValueForField(LHS.getAddress(), anonMember, 1729c186b8fe4a308b53569fe839a3224de70d92ab0eAnders Carlsson /*IsUnion=*/true, 0); 1730e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian FieldType = anonMember->getType(); 1731e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian } 173250b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian } 17331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1734e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only"); 173550b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian Expr *RhsExpr = *Member->arg_begin(); 1736e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman RValue RHS; 1737e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman if (FieldType->isReferenceType()) 1738e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman RHS = EmitReferenceBindingToExpr(RhsExpr, FieldType, 1739e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman /*IsInitializer=*/true); 1740e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman else 1741e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman RHS = RValue::get(EmitScalarExpr(RhsExpr, true)); 1742e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman EmitStoreThroughLValue(RHS, LHS, FieldType); 1743e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian } 1744e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian } 1745f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump 17460880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) { 17471d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian // Nontrivial default constructor with no initializer list. It may still 17481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // have bases classes and/or contain non-static data members which require 17490880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // construction. 17501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (CXXRecordDecl::base_class_const_iterator Base = 17510880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian ClassDecl->bases_begin(); 17520880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 17530880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // FIXME. copy assignment of virtual base NYI 17540880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (Base->isVirtual()) 17550880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 17561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17570880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *BaseClassDecl 17580880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 17590880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (BaseClassDecl->hasTrivialConstructor()) 17600880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 17611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (CXXConstructorDecl *BaseCX = 17620880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian BaseClassDecl->getDefaultConstructor(getContext())) { 17630880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LoadOfThis = LoadCXXThis(); 17645a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl, 17655a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson BaseClassDecl, 17665a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 17670880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0); 17680880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 17690880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 17701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17711d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 17721d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian FieldEnd = ClassDecl->field_end(); 17731d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian Field != FieldEnd; ++Field) { 17741d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 17751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1776288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1777f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) 1778f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 17791d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion()) 17801d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian continue; 17811d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian const RecordType *ClassRec = FieldType->getAs<RecordType>(); 17821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CXXRecordDecl *MemberClassDecl = 17830880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian dyn_cast<CXXRecordDecl>(ClassRec->getDecl()); 17840880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (!MemberClassDecl || MemberClassDecl->hasTrivialConstructor()) 17850880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 17861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (CXXConstructorDecl *MamberCX = 17870880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian MemberClassDecl->getDefaultConstructor(getContext())) { 17880880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LoadOfThis = LoadCXXThis(); 17890880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 1790288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian if (Array) { 1791288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1792288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 17931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 1794288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 1795288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitCXXAggrConstructorCall(MamberCX, Array, BaseAddrPtr); 1796288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian } 1797288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian else 17981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 1799288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian 0, 0); 18001d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian } 18011d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian } 18020880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 18031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1804f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump // Initialize the vtable pointer 1805b502d839994cc3828573bd9ea472418e3536f415Mike Stump if (ClassDecl->isDynamicClass()) { 1806f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump if (!LoadOfThis) 1807f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 1808f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *VtableField; 1809f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Type *Ptr8Ty, *PtrPtr8Ty; 18100032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 1811f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0); 1812f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump VtableField = Builder.CreateBitCast(LoadOfThis, PtrPtr8Ty); 1813f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *vtable = GenerateVtable(ClassDecl); 1814f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump Builder.CreateStore(vtable, VtableField); 1815f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump } 1816e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian} 1817426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian 1818426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian/// EmitDtorEpilogue - Emit all code that comes at the end of class's 18191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// destructor. This is to call destructors on members and base classes 1820426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian/// in reverse order of their construction. 1821174754cda4596f3bb2539df61ab2ab7a17aad6bfAnders Carlsson/// FIXME: This needs to take a CXXDtorType. 1822de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlssonvoid CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD, 1823de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson CXXDtorType DtorType) { 1824426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext()); 1825de738fe899b5c1d387dbc66a1122032e694d3d6fAnders Carlsson assert(!ClassDecl->getNumVBases() && 1826de738fe899b5c1d387dbc66a1122032e694d3d6fAnders Carlsson "FIXME: Destruction of virtual bases not supported"); 1827426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian (void)ClassDecl; // prevent warning. 18281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1829426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(), 1830426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian *E = DD->destr_end(); B != E; ++B) { 1831426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian uintptr_t BaseOrMember = (*B); 1832426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (DD->isMemberToDestroy(BaseOrMember)) { 1833426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember); 1834426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian QualType FieldType = getContext().getCanonicalType((FD)->getType()); 18351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1836f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1837f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) 1838f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 1839426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const RecordType *RT = FieldType->getAs<RecordType>(); 1840426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 1841426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (FieldClassDecl->hasTrivialDestructor()) 1842426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian continue; 1843426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian llvm::Value *LoadOfThis = LoadCXXThis(); 1844426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0); 1845f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) { 1846f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1847f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 18481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 1849f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 18501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), 1851f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Array, BaseAddrPtr); 1852f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian } 1853f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian else 1854f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), 1855f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Dtor_Complete, LHS.getAddress()); 1856b3589f44c5d295cd41de2c83f3475116835eeebdMike Stump } else { 1857426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const RecordType *RT = 1858426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs<RecordType>(); 1859426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 1860426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (BaseClassDecl->hasTrivialDestructor()) 1861426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian continue; 18625a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(), 18635a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson ClassDecl, BaseClassDecl, 18645a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 1865426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), 1866de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson DtorType, V); 1867426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian } 1868426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian } 18690880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (DD->getNumBaseOrMemberDestructions() || DD->isTrivial()) 18700880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian return; 18710880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // Case of destructor synthesis with fields and base classes 18721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // which have non-trivial destructors. They must be destructed in 18730880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // reverse order of their construction. 18740880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::SmallVector<FieldDecl *, 16> DestructedFields; 18751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18760880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 18770880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian FieldEnd = ClassDecl->field_end(); 18780880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Field != FieldEnd; ++Field) { 18790880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 1880f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (getContext().getAsConstantArrayType(FieldType)) 1881f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 18820880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (const RecordType *RT = FieldType->getAs<RecordType>()) { 18830880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 18840880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (FieldClassDecl->hasTrivialDestructor()) 18850880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 18860880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian DestructedFields.push_back(*Field); 18870880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 18880880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 18890880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (!DestructedFields.empty()) 18900880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (int i = DestructedFields.size() -1; i >= 0; --i) { 18910880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian FieldDecl *Field = DestructedFields[i]; 18920880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian QualType FieldType = Field->getType(); 18931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1894f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1895f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) 1896f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 18970880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian const RecordType *RT = FieldType->getAs<RecordType>(); 18980880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 18990880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::Value *LoadOfThis = LoadCXXThis(); 19000880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); 1901f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) { 1902f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1903f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 19041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 1905f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 19061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), 1907f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Array, BaseAddrPtr); 1908f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian } 1909f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian else 1910f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), 1911f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Dtor_Complete, LHS.getAddress()); 19120880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 19131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19140880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::SmallVector<CXXRecordDecl*, 4> DestructedBases; 19150880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); 19160880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 19170880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // FIXME. copy assignment of virtual base NYI 19180880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (Base->isVirtual()) 19190880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 19201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19210880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *BaseClassDecl 19220880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 19230880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (BaseClassDecl->hasTrivialDestructor()) 19240880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 19250880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian DestructedBases.push_back(BaseClassDecl); 19260880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 19270880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (DestructedBases.empty()) 19280880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian return; 19290880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (int i = DestructedBases.size() -1; i >= 0; --i) { 19300880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *BaseClassDecl = DestructedBases[i]; 19315a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(), 19325a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson ClassDecl,BaseClassDecl, 19335a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 19340880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), 19350880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Dtor_Complete, V); 19360880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 1937426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian} 19380880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian 1939de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlssonvoid CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, 1940de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson CXXDtorType DtorType, 19410880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::Function *Fn, 19420880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian const FunctionArgList &Args) { 19431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19440ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson const CXXRecordDecl *ClassDecl = Dtor->getParent(); 19450880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian assert(!ClassDecl->hasUserDeclaredDestructor() && 19460880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian "SynthesizeDefaultDestructor - destructor has user declaration"); 19470880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian (void) ClassDecl; 19481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1949de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson StartFunction(GlobalDecl(Dtor, DtorType), Dtor->getResultType(), Fn, Args, 1950de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson SourceLocation()); 1951de1d26b9c1d8823b173e4d77015ad88b4da70559Anders Carlsson EmitDtorEpilogue(Dtor, DtorType); 19520880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian FinishFunction(); 19531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 19546815e941998659a55c20c147861b0f437928c3d8Anders Carlsson 19556815e941998659a55c20c147861b0f437928c3d8Anders Carlsson// FIXME: Move this to CGCXXStmt.cpp 19566815e941998659a55c20c147861b0f437928c3d8Anders Carlssonvoid CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 19576815e941998659a55c20c147861b0f437928c3d8Anders Carlsson // FIXME: We need to do more here. 19586815e941998659a55c20c147861b0f437928c3d8Anders Carlsson EmitStmt(S.getTryBlock()); 19596815e941998659a55c20c147861b0f437928c3d8Anders Carlsson} 1960