CGCXX.cpp revision 5a0f49ebc83e7fe0da07b9964c44b0a7fae270cb
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" 24e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson#include "llvm/ADT/StringExtras.h" 25e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlssonusing namespace clang; 26e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlssonusing namespace CodeGen; 27e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 293b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders CarlssonCodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor, 303b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DeclPtr) { 313b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // FIXME: This is ABI dependent and we use the Itanium ABI. 321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *Int8PtrTy = 340032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(VMContext)); 351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 363b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson std::vector<const llvm::Type *> Params; 373b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 393b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // Get the destructor function type 401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *DtorFnTy = 410032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Params, false); 423b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); 431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 443b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.clear(); 453b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(DtorFnTy); 463b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 473b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 493b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // Get the __cxa_atexit function type 503b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); 511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::FunctionType *AtExitFnTy = 523b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); 531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 543b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, 553b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "__cxa_atexit"); 561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 573b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, 583b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "__dso_handle"); 591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 603b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); 611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 623b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Value *Args[3] = { llvm::ConstantExpr::getBitCast(DtorFn, DtorFnTy), 633b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::ConstantExpr::getBitCast(DeclPtr, Int8PtrTy), 643b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::ConstantExpr::getBitCast(Handle, Int8PtrTy) }; 653b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Builder.CreateCall(AtExitFn, &Args[0], llvm::array_endof(Args)); 663b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson} 673b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, 693b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DeclPtr) { 703b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson assert(D.hasGlobalStorage() && 713b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "VarDecl must have global storage!"); 721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 733b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson const Expr *Init = D.getInit(); 743b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson QualType T = D.getType(); 751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 763b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson if (T->isReferenceType()) { 77622f9dc76bdc4f4d6920907f4fb64a3222aa6566Anders Carlsson ErrorUnsupported(Init, "global variable that binds to a reference"); 783b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } else if (!hasAggregateLLVMType(T)) { 793b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Value *V = EmitScalarExpr(Init); 803b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitStoreOfScalar(V, DeclPtr, T.isVolatileQualified(), T); 813b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } else if (T->isAnyComplexType()) { 823b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitComplexExprIntoAddr(Init, DeclPtr, T.isVolatileQualified()); 833b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } else { 843b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitAggExpr(Init, DeclPtr, T.isVolatileQualified()); 851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 863b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson if (const RecordType *RT = T->getAs<RecordType>()) { 873b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 883b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson if (!RD->hasTrivialDestructor()) 893b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitCXXGlobalDtorRegistration(RD->getDestructor(getContext()), DeclPtr); 903b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } 913b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson } 923b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson} 933b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 9489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlssonvoid 9589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders CarlssonCodeGenModule::EmitCXXGlobalInitFunc() { 9689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson if (CXXGlobalInits.empty()) 9789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson return; 981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 990032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), 10089ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson false); 1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10289ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson // Create our global initialization function. 10389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson // FIXME: Should this be tweakable by targets? 1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Function *Fn = 10589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 10689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson "__cxx_global_initialization", &TheModule); 1071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10889ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 10910c40eee98c600d24437474463b056f323d0cfd2Benjamin Kramer &CXXGlobalInits[0], 11089ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson CXXGlobalInits.size()); 11189ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson AddGlobalCtor(Fn); 11289ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson} 11389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 11489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlssonvoid CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn, 11589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson const VarDecl **Decls, 11689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson unsigned NumDecls) { 1170ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson StartFunction(GlobalDecl(), getContext().VoidTy, Fn, FunctionArgList(), 11889ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson SourceLocation()); 1191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12089ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson for (unsigned i = 0; i != NumDecls; ++i) { 12189ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson const VarDecl *D = Decls[i]; 1221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); 12489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson EmitCXXGlobalVarDeclInit(*D, DeclPtr); 12589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson } 12689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson FinishFunction(); 12789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson} 12889ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 1291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 1301eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenFunction::EmitStaticCXXBlockVarDeclInit(const VarDecl &D, 1313b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::GlobalVariable *GV) { 1320096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbar // FIXME: This should use __cxa_guard_{acquire,release}? 1330096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbar 134e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson assert(!getContext().getLangOptions().ThreadsafeStatics && 135e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson "thread safe statics are currently not supported!"); 136e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 137283a062a633d6e868aa2be319da812341fe73728Anders Carlsson llvm::SmallString<256> GuardVName; 138283a062a633d6e868aa2be319da812341fe73728Anders Carlsson llvm::raw_svector_ostream GuardVOut(GuardVName); 139283a062a633d6e868aa2be319da812341fe73728Anders Carlsson mangleGuardVariable(&D, getContext(), GuardVOut); 1401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 141e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Create the guard variable. 1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::GlobalValue *GuardV = 1430032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson new llvm::GlobalVariable(CGM.getModule(), llvm::Type::getInt64Ty(VMContext), false, 1440096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbar GV->getLinkage(), 1450032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)), 1467765934ad7e157b5fcf925792a38e01b1edbcf8aDaniel Dunbar GuardVName.str()); 1471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 148e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Load the first byte of the guard variable. 1490032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 1501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy), 151e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson "tmp"); 1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 153e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Compare it against 0. 1540032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::getInt8Ty(VMContext)); 155e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool"); 1561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15755e874299f2ad827646a4ca9ea38c402aaeb38c9Daniel Dunbar llvm::BasicBlock *InitBlock = createBasicBlock("init"); 1589615ecb44f549ae9fa2b4db6ff46bc78befbf62cDaniel Dunbar llvm::BasicBlock *EndBlock = createBasicBlock("init.end"); 159e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 160e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // If the guard variable is 0, jump to the initializer code. 161e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson Builder.CreateCondBr(ICmp, InitBlock, EndBlock); 1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 163e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson EmitBlock(InitBlock); 164e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 1653b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitCXXGlobalVarDeclInit(D, GV); 1663b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 1670032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::getInt8Ty(VMContext), 1), 168e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson Builder.CreateBitCast(GuardV, PtrTy)); 1691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 170e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson EmitBlock(EndBlock); 171e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson} 172e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 173b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders CarlssonRValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, 174b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *Callee, 175b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *This, 176b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CallExpr::const_arg_iterator ArgBeg, 177b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CallExpr::const_arg_iterator ArgEnd) { 1781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(MD->isInstance() && 179774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson "Trying to emit a member call expr on a static method!"); 180b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 1814fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor // A call to a trivial destructor requires no code generation. 1824fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor if (const CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(MD)) 1834fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor if (Destructor->isTrivial()) 1844fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor return RValue::get(0); 1851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 186b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 1871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 188b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CallArgList Args; 1891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 190b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson // Push the this ptr. 191b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson Args.push_back(std::make_pair(RValue::get(This), 192b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson MD->getThisType(getContext()))); 1931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 194b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson // And the rest of the call args 195b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); 1961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 197b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson QualType ResultType = MD->getType()->getAsFunctionType()->getResultType(); 198b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), 199b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson Callee, Args, MD); 200b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson} 201b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 202b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders CarlssonRValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { 203b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()); 204b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); 205b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 206e9918d2443ad524e0f488e8f15d9bce4e7373cd1Anders Carlsson const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 2077116da1efe23f90eb22524ac9aa036153b74f482Mike Stump 2081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *Ty = 2091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 210e9918d2443ad524e0f488e8f15d9bce4e7373cd1Anders Carlsson FPT->isVariadic()); 211b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *This; 2121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 213774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson if (ME->isArrow()) 214b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson This = EmitScalarExpr(ME->getBase()); 215774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson else { 216774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson LValue BaseLV = EmitLValue(ME->getBase()); 217b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson This = BaseLV.getAddress(); 218774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson } 219f0070dbae9535836ad41711081465dec2259786bMike Stump 220bd4c4aebe6035e7a7125470cc9f0f92511230ee3Douglas Gregor // C++ [class.virtual]p12: 2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Explicit qualification with the scope operator (5.1) suppresses the 222bd4c4aebe6035e7a7125470cc9f0f92511230ee3Douglas Gregor // virtual call mechanism. 223f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::Value *Callee; 2240979c805475d1ba49b5d6ef93c4d2ce6d2eab6edDouglas Gregor if (MD->isVirtual() && !ME->hasQualifier()) 225f0070dbae9535836ad41711081465dec2259786bMike Stump Callee = BuildVirtualCall(MD, This, Ty); 2261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (const CXXDestructorDecl *Destructor 2274fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor = dyn_cast<CXXDestructorDecl>(MD)) 2284fe95f99a2693f1145785ea5835ba6937e49c730Douglas Gregor Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); 2290979c805475d1ba49b5d6ef93c4d2ce6d2eab6edDouglas Gregor else 230555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson Callee = CGM.GetAddrOfFunction(MD, Ty); 2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return EmitCXXMemberCall(MD, Callee, This, 233b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CE->arg_begin(), CE->arg_end()); 234774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson} 2355f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson 2361eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpRValue 2370f294632f36459174199b77699e339715244b5abAnders CarlssonCodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, 2380f294632f36459174199b77699e339715244b5abAnders Carlsson const CXXMethodDecl *MD) { 2391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(MD->isInstance() && 2400f294632f36459174199b77699e339715244b5abAnders Carlsson "Trying to emit a member call expr on a static method!"); 2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 242ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian if (MD->isCopyAssignment()) { 243ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext()); 244ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian if (ClassDecl->hasTrivialCopyAssignment()) { 245ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyAssignment() && 246ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); 247ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 248ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); 249ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian QualType Ty = E->getType(); 250ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian EmitAggregateCopy(This, Src, Ty); 251ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian return RValue::get(This); 252ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian } 253ad25883a644dd6b52c7923dd128a7d05fb26213cFariborz Jahanian } 2541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2550f294632f36459174199b77699e339715244b5abAnders Carlsson const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 2561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *Ty = 2571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 258ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FPT->isVariadic()); 259555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, Ty); 2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2610f294632f36459174199b77699e339715244b5abAnders Carlsson llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 2621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2630f294632f36459174199b77699e339715244b5abAnders Carlsson return EmitCXXMemberCall(MD, Callee, This, 2640f294632f36459174199b77699e339715244b5abAnders Carlsson E->arg_begin() + 1, E->arg_end()); 2650f294632f36459174199b77699e339715244b5abAnders Carlsson} 2660f294632f36459174199b77699e339715244b5abAnders Carlsson 2675f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlssonllvm::Value *CodeGenFunction::LoadCXXThis() { 2681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(isa<CXXMethodDecl>(CurFuncDecl) && 2695f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson "Must be in a C++ member function decl to load 'this'"); 2705f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() && 2715f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson "Must be in a C++ member function decl to load 'this'"); 2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2735f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson // FIXME: What if we're inside a block? 274f5408fe484495ee4efbdd709c8a2c2fdbbbdb328Mike Stump // ans: See how CodeGenFunction::LoadObjCSelf() uses 275f5408fe484495ee4efbdd709c8a2c2fdbbbdb328Mike Stump // CodeGenFunction::BlockForwardSelf() for how to do this. 2765f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); 2775f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson} 27895d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlsson 279288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested) 280288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// for-loop to call the default constructor on individual members of the 281288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// array. 'Array' is the array type, 'This' is llvm pointer of the start 282288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// of the array and 'D' is the default costructor Decl for elements of the 283288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// array. It is assumed that all relevant checks have been made by the 284288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian/// caller. 285288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanianvoid 286288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz JahanianCodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, 287288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian const ArrayType *Array, 288288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::Value *This) { 289288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); 290288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian assert(CA && "Do we support VLA for construction ?"); 2911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 292288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Create a temporary for the loop index and initialize it with 0. 2930de78998e7bda473b408437053e48661b510d453Fariborz Jahanian llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), 294288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian "loop.index"); 2951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* zeroConstant = 2960de78998e7bda473b408437053e48661b510d453Fariborz Jahanian llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); 297288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Builder.CreateStore(zeroConstant, IndexPtr, false); 2981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 299288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Start the loop with a block that tests the condition. 300288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 301288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 3021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 303288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(CondBlock); 3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 305288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 307288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Generate: if (loop-index < number-of-elements fall to the loop body, 308288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // otherwise, go to the block after the for-loop. 3094f68d537c3f072366b25f3137f052eee36fddfcdFariborz Jahanian uint64_t NumElements = getContext().getConstantArrayElementCount(CA); 3101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value * NumElementsPtr = 3114f68d537c3f072366b25f3137f052eee36fddfcdFariborz Jahanian llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); 312288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 3131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, 314288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian "isless"); 315288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // If the condition is true, execute the body. 316288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Builder.CreateCondBr(IsLess, ForBody, AfterFor); 3171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 318288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(ForBody); 3191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 320288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 321288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Inside the loop body, emit the constructor call on the array element. 322995d2818a11395b15995694a30f842a0e4fdee4fFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 3234f68d537c3f072366b25f3137f052eee36fddfcdFariborz Jahanian llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx"); 3244f68d537c3f072366b25f3137f052eee36fddfcdFariborz Jahanian EmitCXXConstructorCall(D, Ctor_Complete, Address, 0, 0); 3251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 326288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(ContinueBlock); 3271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 328288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Emit the increment of the loop counter. 329288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); 330288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 331288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); 332288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Builder.CreateStore(NextVal, IndexPtr, false); 3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 334288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Finally, branch back up to the condition for the next iteration. 335288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBranch(CondBlock); 3361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 337288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian // Emit the fall-through block. 338288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitBlock(AfterFor, true); 339288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian} 340288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian 3411c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian/// EmitCXXAggrDestructorCall - calls the default destructor on array 3421c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian/// elements in reverse order of construction. 343b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlssonvoid 344f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz JahanianCodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, 345f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian const ArrayType *Array, 346f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian llvm::Value *This) { 3471c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); 3481c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian assert(CA && "Do we support VLA for destruction ?"); 3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *One = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 3501c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian 1); 3510de78998e7bda473b408437053e48661b510d453Fariborz Jahanian uint64_t ElementCount = getContext().getConstantArrayElementCount(CA); 3521c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Create a temporary for the loop index and initialize it with count of 3531c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // array elements. 3541c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), 3551c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian "loop.index"); 3561c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Index = ElementCount; 3571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* UpperCount = 3581c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), ElementCount); 3591c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Builder.CreateStore(UpperCount, IndexPtr, false); 3601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3611c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Start the loop with a block that tests the condition. 3621c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 3631c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3651c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(CondBlock); 3661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3671c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 3681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3691c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Generate: if (loop-index != 0 fall to the loop body, 3701c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // otherwise, go to the block after the for-loop. 3711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* zeroConstant = 3721c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); 3731c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 3741c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant, 3751c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian "isne"); 3761c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // If the condition is true, execute the body. 3771c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Builder.CreateCondBr(IsNE, ForBody, AfterFor); 3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3791c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(ForBody); 3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3811c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 3821c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Inside the loop body, emit the constructor call on the array element. 3831c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 3841c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateSub(Counter, One); 3851c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx"); 3861c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitCXXDestructorCall(D, Dtor_Complete, Address); 3871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3881c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(ContinueBlock); 3891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3901c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Emit the decrement of the loop counter. 3911c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 3921c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Counter = Builder.CreateSub(Counter, One, "dec"); 3931c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian Builder.CreateStore(Counter, IndexPtr, false); 3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3951c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Finally, branch back up to the condition for the next iteration. 3961c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBranch(CondBlock); 3971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3981c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian // Emit the fall-through block. 3991c536bf6bbb0cdc039cff754825b36f9abfe0629Fariborz Jahanian EmitBlock(AfterFor, true); 400f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian} 401f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian 402f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanianvoid 4031eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, 4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CXXCtorType Type, 405b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson llvm::Value *This, 406b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson CallExpr::const_arg_iterator ArgBeg, 407b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson CallExpr::const_arg_iterator ArgEnd) { 408343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian if (D->isCopyConstructor(getContext())) { 409343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(D->getDeclContext()); 410343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian if (ClassDecl->hasTrivialCopyConstructor()) { 411343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyConstructor() && 412343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian "EmitCXXConstructorCall - user declared copy constructor"); 413343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian const Expr *E = (*ArgBeg); 414343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian QualType Ty = E->getType(); 415343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian llvm::Value *Src = EmitLValue(E).getAddress(); 416343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian EmitAggregateCopy(This, Src, Ty); 417343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian return; 418343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian } 419343a3cf57ee950b024bade8b6b0a2b51663f43cdFariborz Jahanian } 4201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 421b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); 422b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 423b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson EmitCXXMemberCall(D, Callee, This, ArgBeg, ArgEnd); 424b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson} 425b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson 4261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D, 4277267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson CXXDtorType Type, 4287267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson llvm::Value *This) { 4297267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(D, Type); 4301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4317267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson EmitCXXMemberCall(D, Callee, This, 0, 0); 4327267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson} 4337267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson 4341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 4351eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, 43631ccf377f4a676eb6c205b47eef435de616d5e2dAnders Carlsson const CXXConstructExpr *E) { 437b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson assert(Dest && "Must have a destination!"); 4381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *RD = 4406217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); 441b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson if (RD->hasTrivialConstructor()) 442b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson return; 4436904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian 4441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Code gen optimization to eliminate copy constructor and return 4456904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian // its first argument instead. 44692f5822df6a0d7571df44b5d279ed4f017fbb0e6Anders Carlsson if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { 4476904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian CXXConstructExpr::const_arg_iterator i = E->arg_begin(); 4481cf9ff87ee235ad252332a96699abdb32bd6facbFariborz Jahanian EmitAggExpr((*i), Dest, false); 4491cf9ff87ee235ad252332a96699abdb32bd6facbFariborz Jahanian return; 4506904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian } 451b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson // Call the constructor. 4521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest, 453b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson E->arg_begin(), E->arg_end()); 454b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson} 455b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson 456a00703dccbdc6cc4a293db38477dea7db5538c7eAnders Carlssonllvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { 457ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson if (E->isArray()) { 458ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson ErrorUnsupported(E, "new[] expression"); 45903e205031b08669f05c41eed5b896fc94c4a12bbOwen Anderson return llvm::UndefValue::get(ConvertType(E->getType())); 460ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 4611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 462ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType AllocType = E->getAllocatedType(); 463ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson FunctionDecl *NewFD = E->getOperatorNew(); 464ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson const FunctionProtoType *NewFTy = NewFD->getType()->getAsFunctionProtoType(); 4651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 466ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson CallArgList NewArgs; 467ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 468ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // The allocation size is the first argument. 469ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType SizeTy = getContext().getSizeType(); 4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *AllocSize = 4711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::ConstantInt::get(ConvertType(SizeTy), 472ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson getContext().getTypeSize(AllocType) / 8); 473ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 474ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); 4751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 476ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // Emit the rest of the arguments. 477ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // FIXME: Ideally, this should just use EmitCallArgs. 478ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); 479ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 480ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // First, use the types from the function type. 481ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // We start at 1 here because the first argument (the allocation size) 482ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // has already been emitted. 483ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { 484ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType ArgType = NewFTy->getArgType(i); 4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 486ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). 4871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump getTypePtr() == 4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump getContext().getCanonicalType(NewArg->getType()).getTypePtr() && 489ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson "type mismatch in call argument!"); 4901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 492ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson ArgType)); 4931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 494ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 4951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Either we've emitted all the call args, or we have a call to a 497ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // variadic function. 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && 499ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson "Extra arguments in non-variadic function!"); 5001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 501ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // If we still have any arguments, emit them using the type of the argument. 5021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); 503ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArg != NewArgEnd; ++NewArg) { 504ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType ArgType = NewArg->getType(); 505ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 506ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson ArgType)); 507ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 508ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 509ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // Emit the call to new. 5101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump RValue RV = 511ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), 512555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD); 513ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 514d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // If an allocation function is declared with an empty exception specification 515d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // it returns null to indicate failure to allocate storage. [expr.new]p13. 516d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // (We don't need to check for null when there's no new initializer and 517d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // we're allocating a POD type). 518d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && 519d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson !(AllocType->isPODType() && !E->hasInitializer()); 520ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 521f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::BasicBlock *NewNull = 0; 522f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::BasicBlock *NewNotNull = 0; 523f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::BasicBlock *NewEnd = 0; 524f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 525f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::Value *NewPtr = RV.getScalarVal(); 526f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 527d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson if (NullCheckResult) { 528f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewNull = createBasicBlock("new.null"); 529f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewNotNull = createBasicBlock("new.notnull"); 530f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewEnd = createBasicBlock("new.end"); 5311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *IsNull = 5331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Builder.CreateICmpEQ(NewPtr, 534c9c88b4159791c48e486ca94e3743b5979e2b7a6Owen Anderson llvm::Constant::getNullValue(NewPtr->getType()), 535f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson "isnull"); 5361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 537f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson Builder.CreateCondBr(IsNull, NewNull, NewNotNull); 538f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson EmitBlock(NewNotNull); 539d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson } 5401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 541f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); 5421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5436d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson if (AllocType->isPODType()) { 544215bd208d6eeff397bc4316d046ea8b4633efedfAnders Carlsson if (E->getNumConstructorArgs() > 0) { 5451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(E->getNumConstructorArgs() == 1 && 5466d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson "Can only have one argument to initializer of POD type."); 5476d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson 5486d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson const Expr *Init = E->getConstructorArg(0); 5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (!hasAggregateLLVMType(AllocType)) 5516d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson Builder.CreateStore(EmitScalarExpr(Init), NewPtr); 5523923e95280210ef877153f0c3dbab12d6ed2ad43Anders Carlsson else if (AllocType->isAnyComplexType()) 5533923e95280210ef877153f0c3dbab12d6ed2ad43Anders Carlsson EmitComplexExprIntoAddr(Init, NewPtr, AllocType.isVolatileQualified()); 554627a3e573f1d9f0429d62c7ceb742a21cdabfce0Anders Carlsson else 555627a3e573f1d9f0429d62c7ceb742a21cdabfce0Anders Carlsson EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); 5566d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson } 557d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson } else { 5581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Call the constructor. 559d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson CXXConstructorDecl *Ctor = E->getConstructor(); 5601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, 5621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E->constructor_arg_begin(), 563d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson E->constructor_arg_end()); 564ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 565d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson 566f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson if (NullCheckResult) { 567f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson Builder.CreateBr(NewEnd); 568f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson EmitBlock(NewNull); 569f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson Builder.CreateBr(NewEnd); 570f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson EmitBlock(NewEnd); 5711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 572f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); 573f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson PHI->reserveOperandSpace(2); 574f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson PHI->addIncoming(NewPtr, NewNotNull); 575c9c88b4159791c48e486ca94e3743b5979e2b7a6Owen Anderson PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull); 5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 577f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewPtr = PHI; 578f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson } 5791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 580d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson return NewPtr; 581a00703dccbdc6cc4a293db38477dea7db5538c7eAnders Carlsson} 582a00703dccbdc6cc4a293db38477dea7db5538c7eAnders Carlsson 58360e282cc1e508be327b0481cecedc206873cb86aAnders Carlssonvoid CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { 58460e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson if (E->isArrayForm()) { 58560e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson ErrorUnsupported(E, "delete[] expression"); 58660e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson return; 58760e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson }; 58860e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson 5891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType DeleteTy = 59060e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson E->getArgument()->getType()->getAs<PointerType>()->getPointeeType(); 5911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59260e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson llvm::Value *Ptr = EmitScalarExpr(E->getArgument()); 5931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 59460e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson // Null check the pointer. 59560e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); 59660e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); 59760e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson 5981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *IsNull = 59960e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()), 60060e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson "isnull"); 6011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60260e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); 60360e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson EmitBlock(DeleteNotNull); 6041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 60560e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson // Call the destructor if necessary. 60660e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson if (const RecordType *RT = DeleteTy->getAs<RecordType>()) { 60760e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { 60860e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson if (!RD->hasTrivialDestructor()) { 60960e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson const CXXDestructorDecl *Dtor = RD->getDestructor(getContext()); 61060e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson if (Dtor->isVirtual()) { 61160e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson ErrorUnsupported(E, "delete expression with virtual destructor"); 61260e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson return; 61360e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson } 6141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 61560e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr); 61660e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson } 61760e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson } 61860e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson } 6191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62060e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson // Call delete. 62160e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson FunctionDecl *DeleteFD = E->getOperatorDelete(); 6221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const FunctionProtoType *DeleteFTy = 62360e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson DeleteFD->getType()->getAsFunctionProtoType(); 6241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62560e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson CallArgList DeleteArgs; 62660e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson 62760e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson QualType ArgTy = DeleteFTy->getArgType(0); 62860e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); 62960e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); 6301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63160e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson // Emit the call to delete. 6321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), 63360e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson DeleteArgs), 634555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson CGM.GetAddrOfFunction(DeleteFD), 63560e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson DeleteArgs, DeleteFD); 6361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 63760e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson EmitBlock(DeleteEnd); 63860e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson} 63960e282cc1e508be327b0481cecedc206873cb86aAnders Carlsson 64095d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlssonvoid CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { 6412a131fbca2a51085dc083b8c56a2d4ced3cf1413Anders Carlsson EmitGlobal(GlobalDecl(D, Ctor_Complete)); 6422a131fbca2a51085dc083b8c56a2d4ced3cf1413Anders Carlsson EmitGlobal(GlobalDecl(D, Ctor_Base)); 64395d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlsson} 644363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson 6451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, 64627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXCtorType Type) { 6471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 64827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type); 6491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6500ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); 6511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 65227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetFunctionDefinitionAttributes(D, Fn); 65327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetLLVMFunctionAttributesForDefinition(D, Fn); 65427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 65527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 656363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlssonllvm::Function * 6571eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, 658363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson CXXCtorType Type) { 659363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson const llvm::FunctionType *FTy = 660363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 6611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 662363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson const char *Name = getMangledCXXCtorName(D, Type); 663b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner return cast<llvm::Function>( 664b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 665363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson} 66627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 6671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpconst char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D, 66827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXCtorType Type) { 66927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::SmallString<256> Name; 67027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::raw_svector_ostream Out(Name); 67127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson mangleCXXCtor(D, Type, Context, Out); 6721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 67327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson Name += '\0'; 67427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson return UniqueMangledName(Name.begin(), Name.end()); 67527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 67627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 67727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonvoid CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) { 67827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson EmitCXXDestructor(D, Dtor_Complete); 67927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson EmitCXXDestructor(D, Dtor_Base); 68027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 68127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 6821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, 68327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 68427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type); 6851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6860ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson CodeGenFunction(*this).GenerateCode(GlobalDecl(D, Type), Fn); 6871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 68827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetFunctionDefinitionAttributes(D, Fn); 68927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetLLVMFunctionAttributesForDefinition(D, Fn); 69027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 69127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 69227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonllvm::Function * 6931eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpCodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, 69427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 69527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson const llvm::FunctionType *FTy = 69627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 6971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 69827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson const char *Name = getMangledCXXDtorName(D, Type); 699b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner return cast<llvm::Function>( 700b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 70127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 70227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 7031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpconst char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, 70427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 70527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::SmallString<256> Name; 70627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::raw_svector_ostream Out(Name); 70727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson mangleCXXDtor(D, Type, Context, Out); 7081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson Name += '\0'; 71027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson return UniqueMangledName(Name.begin(), Name.end()); 71127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 712e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian 71332f3701853a8237704065c77abc17369dd02c39bMike Stumpllvm::Constant *CodeGenModule::GenerateRtti(const CXXRecordDecl *RD) { 714738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::Type *Ptr8Ty; 7150032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 716cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump llvm::Constant *Rtti = llvm::Constant::getNullValue(Ptr8Ty); 717738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 718738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump if (!getContext().getLangOptions().Rtti) 719cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump return Rtti; 720738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 721738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::SmallString<256> OutName; 722738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::raw_svector_ostream Out(OutName); 723738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump QualType ClassTy; 724e607ed068334bacb8d7b093996b4671c6ca79e25Mike Stump ClassTy = getContext().getTagDeclType(RD); 725738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump mangleCXXRtti(ClassTy, getContext(), Out); 726738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::GlobalVariable::LinkageTypes linktype; 727738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 728738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump std::vector<llvm::Constant *> info; 7294ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump // assert(0 && "FIXME: implement rtti descriptor"); 730738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump // FIXME: descriptor 731738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); 7324ef980984fd0e131fca3f9e6ba15e8a79cabf88cMike Stump // assert(0 && "FIXME: implement rtti ts"); 733738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump // FIXME: TS 734738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); 735738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 736738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::Constant *C; 737738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, info.size()); 738738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump C = llvm::ConstantArray::get(type, info); 73932f3701853a8237704065c77abc17369dd02c39bMike Stump Rtti = new llvm::GlobalVariable(getModule(), type, true, linktype, C, 7407765934ad7e157b5fcf925792a38e01b1edbcf8aDaniel Dunbar Out.str()); 741cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump Rtti = llvm::ConstantExpr::getBitCast(Rtti, Ptr8Ty); 742cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump return Rtti; 743738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump} 744738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 745eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stumpclass VtableBuilder { 746f0070dbae9535836ad41711081465dec2259786bMike Stumppublic: 747f0070dbae9535836ad41711081465dec2259786bMike Stump /// Index_t - Vtable index type. 748f0070dbae9535836ad41711081465dec2259786bMike Stump typedef uint64_t Index_t; 749f0070dbae9535836ad41711081465dec2259786bMike Stumpprivate: 7507c435fa7f7666b22abbe8494c537ebc25209223dMike Stump std::vector<llvm::Constant *> &methods; 75115a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump std::vector<llvm::Constant *> submethods; 7527c435fa7f7666b22abbe8494c537ebc25209223dMike Stump llvm::Type *Ptr8Ty; 753b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// Class - The most derived class that this vtable is being built for. 75432f3701853a8237704065c77abc17369dd02c39bMike Stump const CXXRecordDecl *Class; 755b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// BLayout - Layout for the most derived class that this vtable is being 756b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// built for. 757b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump const ASTRecordLayout &BLayout; 758ee560f3b1fda7d5ec68b85b497c3e326ac5c3fdbMike Stump llvm::SmallSet<const CXXRecordDecl *, 32> IndirectPrimary; 7597fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump llvm::SmallSet<const CXXRecordDecl *, 32> SeenVBase; 76032f3701853a8237704065c77abc17369dd02c39bMike Stump llvm::Constant *rtti; 7617c435fa7f7666b22abbe8494c537ebc25209223dMike Stump llvm::LLVMContext &VMContext; 76265defe3ee7be121aef50b498e51f1d831b4a15f3Mike Stump CodeGenModule &CGM; // Per-module state. 763b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// Index - Maps a method decl into a vtable index. Useful for virtual 764b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump /// dispatch codegen. 765f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> Index; 76615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall; 76715a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset; 7686e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump typedef std::pair<Index_t, Index_t> CallOffset; 7696e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t; 77077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks_t Thunks; 7716e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump typedef llvm::DenseMap<const CXXMethodDecl *, 7726e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump std::pair<CallOffset, CallOffset> > CovariantThunks_t; 7736e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CovariantThunks_t CovariantThunks; 77415a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump std::vector<Index_t> VCalls; 775552b275708a25aa1d939b2b77e5419a0b4b8e6d4Mike Stump typedef CXXRecordDecl::method_iterator method_iter; 776ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump // FIXME: Linkage should follow vtable 777ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump const bool Extern; 77877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump const uint32_t LLVMPointerWidth; 77977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t extra; 7807c435fa7f7666b22abbe8494c537ebc25209223dMike Stumppublic: 781eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump VtableBuilder(std::vector<llvm::Constant *> &meth, 782eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump const CXXRecordDecl *c, 783eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump CodeGenModule &cgm) 784b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump : methods(meth), Class(c), BLayout(cgm.getContext().getASTRecordLayout(c)), 785b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump rtti(cgm.GenerateRtti(c)), VMContext(cgm.getModule().getContext()), 78677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump CGM(cgm), Extern(true), 78777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { 7887c435fa7f7666b22abbe8494c537ebc25209223dMike Stump Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 7897c435fa7f7666b22abbe8494c537ebc25209223dMike Stump } 79032f3701853a8237704065c77abc17369dd02c39bMike Stump 791f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; } 792b46c92dfedf02239e7c73b9a18dcf09071731793Mike Stump 79315a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::Constant *wrap(Index_t i) { 7947c435fa7f7666b22abbe8494c537ebc25209223dMike Stump llvm::Constant *m; 79515a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i); 79615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); 79715a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 7987c435fa7f7666b22abbe8494c537ebc25209223dMike Stump 79915a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::Constant *wrap(llvm::Constant *m) { 80015a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump return llvm::ConstantExpr::getBitCast(m, Ptr8Ty); 80180a0e32d60e4ff7d78f411e73f3e8dea769ed313Mike Stump } 8024c3aedd3f1fff57d1906b0cdfa7a9ec81a361b2dMike Stump 8037fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets, 804b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump const CXXRecordDecl *RD, uint64_t Offset) { 8057fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump for (CXXRecordDecl::base_class_const_iterator i =RD->bases_begin(), 8067fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump e = RD->bases_end(); i != e; ++i) { 8071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 8087fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 8097fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump if (i->isVirtual() && !SeenVBase.count(Base)) { 8107fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump SeenVBase.insert(Base); 811b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8; 81215a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump llvm::Constant *m = wrap(BaseOffset); 81315a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump m = wrap((0?700:0) + BaseOffset); 8147fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump offsets.push_back(m); 8157fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump } 816b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump GenerateVBaseOffsets(offsets, Base, Offset); 8177fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump } 8187fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump } 8197fa0d93a3bbe290244f4f157078d9a0d6e87b44fMike Stump 820b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump void StartNewTable() { 821b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump SeenVBase.clear(); 822b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump } 82365defe3ee7be121aef50b498e51f1d831b4a15f3Mike Stump 82435191b61db617aefba43b8add88a2ec88af67592Mike Stump bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m, 825dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump bool MorallyVirtual, Index_t Offset) { 826b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump typedef CXXMethodDecl::method_iterator meth_iter; 827b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 828b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // FIXME: Don't like the nested loops. For very large inheritance 829b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // heirarchies we could have a table on the side with the final overridder 830b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // and just replace each instance of an overridden method once. Would be 831b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // nice to measure the cost/benefit on real code. 832b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 833b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump for (meth_iter mi = MD->begin_overridden_methods(), 834b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump e = MD->end_overridden_methods(); 835b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump mi != e; ++mi) { 836b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump const CXXMethodDecl *OMD = *mi; 837b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump llvm::Constant *om; 838555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson om = CGM.GetAddrOfFunction(OMD, Ptr8Ty); 839b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty); 840b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 841dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump for (Index_t i = 0, e = submethods.size(); 842f0070dbae9535836ad41711081465dec2259786bMike Stump i != e; ++i) { 843b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // FIXME: begin_overridden_methods might be too lax, covariance */ 84477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (submethods[i] != om) 84577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump continue; 8466e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump QualType nc_oret = OMD->getType()->getAsFunctionType()->getResultType(); 8476e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CanQualType oret = CGM.getContext().getCanonicalType(nc_oret); 8486e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump QualType nc_ret = MD->getType()->getAsFunctionType()->getResultType(); 8496e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CanQualType ret = CGM.getContext().getCanonicalType(nc_ret); 8506e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CallOffset ReturnOffset = std::make_pair(0, 0); 8516e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump if (oret != ret) { 8526e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // FIXME: calculate offsets for covariance 8536e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ReturnOffset = std::make_pair(42,42); 8546e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump } 855dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump Index[MD] = i; 85677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump submethods[i] = m; 85777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump 85877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks.erase(OMD); 85977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (MorallyVirtual) { 86077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t &idx = VCall[OMD]; 86177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (idx == 0) { 862dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump VCallOffset[MD] = Offset/8; 86377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump idx = VCalls.size()+1; 86477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump VCalls.push_back(0); 865dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump } else { 866dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump VCallOffset[MD] = VCallOffset[OMD]; 867dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump VCalls[idx-1] = -VCallOffset[OMD] + Offset/8; 86815a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 86977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump VCall[MD] = idx; 8706e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CallOffset ThisOffset; 8716e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // FIXME: calculate non-virtual offset 8726e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ThisOffset = std::make_pair(0, -((idx+extra+2)*LLVMPointerWidth/8)); 8736e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump if (ReturnOffset.first || ReturnOffset.second) 8746e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CovariantThunks[MD] = std::make_pair(ThisOffset, ReturnOffset); 8756e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump else 8766e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Thunks[MD] = ThisOffset; 87735191b61db617aefba43b8add88a2ec88af67592Mike Stump return true; 878b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump } 87977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump#if 0 88077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump // FIXME: finish off 88177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t O = VCallOffset[OMD] - Offset/8; 88277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (O) { 88377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks[MD] = std::make_pair(O, 0); 88477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 88577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump#endif 88677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump return true; 88765defe3ee7be121aef50b498e51f1d831b4a15f3Mike Stump } 888bc16aeab78748cca01a9d84fff71dd1109633ecdMike Stump } 889b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 89035191b61db617aefba43b8add88a2ec88af67592Mike Stump return false; 89135191b61db617aefba43b8add88a2ec88af67592Mike Stump } 89235191b61db617aefba43b8add88a2ec88af67592Mike Stump 89398cc71003d385561224e3711cd34c5b03f27ccdcMike Stump void InstallThunks() { 89477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump for (Thunks_t::iterator i = Thunks.begin(), e = Thunks.end(); 89577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump i != e; ++i) { 89677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump const CXXMethodDecl *MD = i->first; 89777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t idx = Index[MD]; 89877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t nv_O = i->second.first; 89977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Index_t v_O = i->second.second; 90098cc71003d385561224e3711cd34c5b03f27ccdcMike Stump submethods[idx] = CGM.BuildThunk(MD, Extern, nv_O, v_O); 90177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 90277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump Thunks.clear(); 9036e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump for (CovariantThunks_t::iterator i = CovariantThunks.begin(), 9046e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump e = CovariantThunks.end(); 9056e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump i != e; ++i) { 9066e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump const CXXMethodDecl *MD = i->first; 9076e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t idx = Index[MD]; 9086e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t nv_t = i->second.first.first; 9096e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t v_t = i->second.first.second; 9106e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t nv_r = i->second.second.first; 9116e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Index_t v_r = i->second.second.second; 9126e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, nv_t, v_t, nv_r, 9136e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump v_r); 9146e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump } 9156e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CovariantThunks.clear(); 91677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 91777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump 918dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump void OverrideMethods(std::vector<std::pair<const CXXRecordDecl *, 919dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > *Path, bool MorallyVirtual) { 920dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump for (std::vector<std::pair<const CXXRecordDecl *, 921dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> >::reverse_iterator i =Path->rbegin(), 92298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump e = Path->rend(); i != e; ++i) { 923dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump const CXXRecordDecl *RD = i->first; 924dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t Offset = i->second; 92598cc71003d385561224e3711cd34c5b03f27ccdcMike Stump for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; 92698cc71003d385561224e3711cd34c5b03f27ccdcMike Stump ++mi) 92798cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (mi->isVirtual()) { 92898cc71003d385561224e3711cd34c5b03f27ccdcMike Stump const CXXMethodDecl *MD = *mi; 929c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson llvm::Constant *m = wrap(CGM.GetAddrOfFunction(MD)); 930dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump OverrideMethod(MD, m, MorallyVirtual, Offset); 93198cc71003d385561224e3711cd34c5b03f27ccdcMike Stump } 93298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump } 933f9a883c27e3b5724a5a59499691fa109eb5032f8Mike Stump } 934f9a883c27e3b5724a5a59499691fa109eb5032f8Mike Stump 9356d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump void AddMethod(const CXXMethodDecl *MD, bool MorallyVirtual, Index_t Offset) { 936c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson llvm::Constant *m = 0; 9373fec4c605e0dd074422bca21626c036f52dab31dAnders Carlsson if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) 938c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson m = wrap(CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete)); 9393fec4c605e0dd074422bca21626c036f52dab31dAnders Carlsson else 940c7cba15f5fd86b96c03c57a1d307dde468f7399bAnders Carlsson m = wrap(CGM.GetAddrOfFunction(MD)); 9413fec4c605e0dd074422bca21626c036f52dab31dAnders Carlsson 94277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump // If we can find a previously allocated slot for this, reuse it. 943dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump if (OverrideMethod(MD, m, MorallyVirtual, Offset)) 94435191b61db617aefba43b8add88a2ec88af67592Mike Stump return; 9451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 946b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump // else allocate a new slot. 94715a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump Index[MD] = submethods.size(); 948dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump submethods.push_back(m); 94915a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump if (MorallyVirtual) { 95015a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump VCallOffset[MD] = Offset/8; 95115a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump Index_t &idx = VCall[MD]; 95215a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump // Allocate the first one, after that, we reuse the previous one. 95315a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump if (idx == 0) { 95415a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump idx = VCalls.size()+1; 95515a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump VCalls.push_back(0); 95615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 95715a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump } 958b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump } 959b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump 9606d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump void AddMethods(const CXXRecordDecl *RD, bool MorallyVirtual, 9616d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump Index_t Offset) { 962b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; 963b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump ++mi) 964b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump if (mi->isVirtual()) 9656d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump AddMethod(*mi, MorallyVirtual, Offset); 966bc16aeab78748cca01a9d84fff71dd1109633ecdMike Stump } 967bc16aeab78748cca01a9d84fff71dd1109633ecdMike Stump 96877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump void NonVirtualBases(const CXXRecordDecl *RD, const ASTRecordLayout &Layout, 96977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump const CXXRecordDecl *PrimaryBase, 97077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump bool PrimaryBaseWasVirtual, bool MorallyVirtual, 97177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t Offset) { 97277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 97377ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump e = RD->bases_end(); i != e; ++i) { 97477ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (i->isVirtual()) 97577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump continue; 9761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 97777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 97877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump if (Base != PrimaryBase || PrimaryBaseWasVirtual) { 97977ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump uint64_t o = Offset + Layout.getBaseClassOffset(Base); 98077ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump StartNewTable(); 981dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump std::vector<std::pair<const CXXRecordDecl *, 982dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > S; 983dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump S.push_back(std::make_pair(RD, Offset)); 98498cc71003d385561224e3711cd34c5b03f27ccdcMike Stump GenerateVtableForBase(Base, MorallyVirtual, o, false, &S); 98577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 98677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 98777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump } 98877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump 9896d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump Index_t end(const CXXRecordDecl *RD, std::vector<llvm::Constant *> &offsets, 9906d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump const ASTRecordLayout &Layout, 9916d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump const CXXRecordDecl *PrimaryBase, 9926d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump bool PrimaryBaseWasVirtual, bool MorallyVirtual, 9936d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump int64_t Offset, bool ForVirtualBase) { 9946d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump StartNewTable(); 9956d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump extra = 0; 9966d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // FIXME: Cleanup. 9976d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump if (!ForVirtualBase) { 9986d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // then virtual base offsets... 9996d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), 10006d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump e = offsets.rend(); i != e; ++i) 10016d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(*i); 10026d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump } 10036d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 10046d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // The vcalls come first... 1005dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump for (std::vector<Index_t>::reverse_iterator i=VCalls.rbegin(), 1006dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump e=VCalls.rend(); 1007dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump i != e; ++i) 10086d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(wrap((0?600:0) + *i)); 10096d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump VCalls.clear(); 10106d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 10116d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump if (ForVirtualBase) { 10126d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // then virtual base offsets... 10136d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(), 10146d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump e = offsets.rend(); i != e; ++i) 10156d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(*i); 10166d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump } 10176d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 10186d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(wrap(-(Offset/8))); 10196d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.push_back(rtti); 10206d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump Index_t AddressPoint = methods.size(); 10216d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 102298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump InstallThunks(); 10236d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump methods.insert(methods.end(), submethods.begin(), submethods.end()); 10246d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump submethods.clear(); 10256d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 10266d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump // and then the non-virtual bases. 10276d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump NonVirtualBases(RD, Layout, PrimaryBase, PrimaryBaseWasVirtual, 10286d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump MorallyVirtual, Offset); 10296d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump return AddressPoint; 10306d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump } 10316d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump 1032078d778d8ea4a3975a985da4e8aaef2d269c82faMike Stump void Primaries(const CXXRecordDecl *RD, bool MorallyVirtual, int64_t Offset) { 10339bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump if (!RD->isDynamicClass()) 10349bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump return; 10359bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 10369bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); 10371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); 10389bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); 10399bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 10409bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump // vtables are composed from the chain of primaries. 10419bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump if (PrimaryBase) { 10429bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump if (PrimaryBaseWasVirtual) 10439bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump IndirectPrimary.insert(PrimaryBase); 1044078d778d8ea4a3975a985da4e8aaef2d269c82faMike Stump Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset); 10459bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump } 10469bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 10479bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump // And add the virtuals for the class to the primary vtable. 10489bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump AddMethods(RD, MorallyVirtual, Offset); 10499bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump } 10509bbe962611ebdcfdd1e5e312113ad4efd13472b2Mike Stump 1051e45c90f53e3fcb59a48e88862aa5cf5f5538556cMike Stump int64_t GenerateVtableForBase(const CXXRecordDecl *RD, 1052a18df0ec71c5c95fb6809d4a80050f7b218f38b5Mike Stump bool MorallyVirtual = false, int64_t Offset = 0, 1053a18df0ec71c5c95fb6809d4a80050f7b218f38b5Mike Stump bool ForVirtualBase = false, 1054dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump std::vector<std::pair<const CXXRecordDecl *, 1055dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > *Path = 0) { 1056bf595a3b1f1737eb60203856ea34b759c4c09c46Mike Stump if (!RD->isDynamicClass()) 1057263b3522add846130ff5f0a85568234e612a81caMike Stump return 0; 1058109b13db3391face0b393c730f0326ca51d25b52Mike Stump 1059109b13db3391face0b393c730f0326ca51d25b52Mike Stump const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); 10601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); 1061109b13db3391face0b393c730f0326ca51d25b52Mike Stump const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); 1062109b13db3391face0b393c730f0326ca51d25b52Mike Stump 106315a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump std::vector<llvm::Constant *> offsets; 1064b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump extra = 0; 1065b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump GenerateVBaseOffsets(offsets, RD, Offset); 1066b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump if (ForVirtualBase) 1067b4d2861371d84a5cc98462676da4e6bb8c2d7c03Mike Stump extra = offsets.size(); 106802cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump 1069109b13db3391face0b393c730f0326ca51d25b52Mike Stump // vtables are composed from the chain of primaries. 1070109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (PrimaryBase) { 1071109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (PrimaryBaseWasVirtual) 1072109b13db3391face0b393c730f0326ca51d25b52Mike Stump IndirectPrimary.insert(PrimaryBase); 1073078d778d8ea4a3975a985da4e8aaef2d269c82faMike Stump Primaries(PrimaryBase, PrimaryBaseWasVirtual|MorallyVirtual, Offset); 1074109b13db3391face0b393c730f0326ca51d25b52Mike Stump } 1075276b9f1d814f4f6551cc3000590759a34185d6daMike Stump 107615a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump // And add the virtuals for the class to the primary vtable. 10776d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump AddMethods(RD, MorallyVirtual, Offset); 107815a24e0e0737c3aa6f85fd18af64c3b6195454c3Mike Stump 107998cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (Path) 1080dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump OverrideMethods(Path, MorallyVirtual); 108198cc71003d385561224e3711cd34c5b03f27ccdcMike Stump 10826d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual, 10836d10eb828b32b7a1058809c59ce6c3e2c46b18d7Mike Stump MorallyVirtual, Offset, ForVirtualBase); 1084276b9f1d814f4f6551cc3000590759a34185d6daMike Stump } 1085276b9f1d814f4f6551cc3000590759a34185d6daMike Stump 108698cc71003d385561224e3711cd34c5b03f27ccdcMike Stump void GenerateVtableForVBases(const CXXRecordDecl *RD, 1087dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t Offset = 0, 1088dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump std::vector<std::pair<const CXXRecordDecl *, 1089dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> > *Path = 0) { 109098cc71003d385561224e3711cd34c5b03f27ccdcMike Stump bool alloc = false; 109198cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (Path == 0) { 109298cc71003d385561224e3711cd34c5b03f27ccdcMike Stump alloc = true; 1093dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump Path = new std::vector<std::pair<const CXXRecordDecl *, 1094dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t> >; 109598cc71003d385561224e3711cd34c5b03f27ccdcMike Stump } 109698cc71003d385561224e3711cd34c5b03f27ccdcMike Stump // FIXME: We also need to override using all paths to a virtual base, 109798cc71003d385561224e3711cd34c5b03f27ccdcMike Stump // right now, we just process the first path 1098dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump Path->push_back(std::make_pair(RD, Offset)); 1099109b13db3391face0b393c730f0326ca51d25b52Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 1100109b13db3391face0b393c730f0326ca51d25b52Mike Stump e = RD->bases_end(); i != e; ++i) { 11011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *Base = 1102109b13db3391face0b393c730f0326ca51d25b52Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 1103109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (i->isVirtual() && !IndirectPrimary.count(Base)) { 1104109b13db3391face0b393c730f0326ca51d25b52Mike Stump // Mark it so we don't output it twice. 1105109b13db3391face0b393c730f0326ca51d25b52Mike Stump IndirectPrimary.insert(Base); 1106b9871a253d351e8776cfa5483d6330d5dffe4562Mike Stump StartNewTable(); 1107b983744cccb7e2e5c2bc96de3dcc090ed17fa392Mike Stump int64_t BaseOffset = BLayout.getVBaseClassOffset(Base); 110898cc71003d385561224e3711cd34c5b03f27ccdcMike Stump GenerateVtableForBase(Base, true, BaseOffset, true, Path); 1109109b13db3391face0b393c730f0326ca51d25b52Mike Stump } 1110dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump int64_t BaseOffset = Offset; 1111dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump if (i->isVirtual()) 1112dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump BaseOffset = BLayout.getVBaseClassOffset(Base); 1113109b13db3391face0b393c730f0326ca51d25b52Mike Stump if (Base->getNumVBases()) 1114dec025b15c63e0353768e402ad1fd566d97d2be7Mike Stump GenerateVtableForVBases(Base, BaseOffset, Path); 1115109b13db3391face0b393c730f0326ca51d25b52Mike Stump } 111698cc71003d385561224e3711cd34c5b03f27ccdcMike Stump Path->pop_back(); 111798cc71003d385561224e3711cd34c5b03f27ccdcMike Stump if (alloc) 111898cc71003d385561224e3711cd34c5b03f27ccdcMike Stump delete Path; 1119e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump } 1120109b13db3391face0b393c730f0326ca51d25b52Mike Stump}; 11218a12b564923a72224730a467007e61b5701e4aa7Mike Stump 1122f0070dbae9535836ad41711081465dec2259786bMike Stumpclass VtableInfo { 1123f0070dbae9535836ad41711081465dec2259786bMike Stumppublic: 1124f0070dbae9535836ad41711081465dec2259786bMike Stump typedef VtableBuilder::Index_t Index_t; 1125f0070dbae9535836ad41711081465dec2259786bMike Stumpprivate: 1126f0070dbae9535836ad41711081465dec2259786bMike Stump CodeGenModule &CGM; // Per-module state. 1127f0070dbae9535836ad41711081465dec2259786bMike Stump /// Index_t - Vtable index type. 1128f0070dbae9535836ad41711081465dec2259786bMike Stump typedef llvm::DenseMap<const CXXMethodDecl *, Index_t> ElTy; 1129f0070dbae9535836ad41711081465dec2259786bMike Stump typedef llvm::DenseMap<const CXXRecordDecl *, ElTy *> MapTy; 1130f0070dbae9535836ad41711081465dec2259786bMike Stump // FIXME: Move to Context. 1131f0070dbae9535836ad41711081465dec2259786bMike Stump static MapTy IndexFor; 1132f0070dbae9535836ad41711081465dec2259786bMike Stumppublic: 1133f0070dbae9535836ad41711081465dec2259786bMike Stump VtableInfo(CodeGenModule &cgm) : CGM(cgm) { } 1134f0070dbae9535836ad41711081465dec2259786bMike Stump void register_index(const CXXRecordDecl *RD, const ElTy &e) { 1135f0070dbae9535836ad41711081465dec2259786bMike Stump assert(IndexFor.find(RD) == IndexFor.end() && "Don't compute vtbl twice"); 1136f0070dbae9535836ad41711081465dec2259786bMike Stump // We own a copy of this, it will go away shortly. 1137f0070dbae9535836ad41711081465dec2259786bMike Stump new ElTy (e); 1138f0070dbae9535836ad41711081465dec2259786bMike Stump IndexFor[RD] = new ElTy (e); 1139f0070dbae9535836ad41711081465dec2259786bMike Stump } 1140f0070dbae9535836ad41711081465dec2259786bMike Stump Index_t lookup(const CXXMethodDecl *MD) { 1141f0070dbae9535836ad41711081465dec2259786bMike Stump const CXXRecordDecl *RD = MD->getParent(); 1142f0070dbae9535836ad41711081465dec2259786bMike Stump MapTy::iterator I = IndexFor.find(RD); 1143f0070dbae9535836ad41711081465dec2259786bMike Stump if (I == IndexFor.end()) { 1144f0070dbae9535836ad41711081465dec2259786bMike Stump std::vector<llvm::Constant *> methods; 1145f0070dbae9535836ad41711081465dec2259786bMike Stump VtableBuilder b(methods, RD, CGM); 1146a18df0ec71c5c95fb6809d4a80050f7b218f38b5Mike Stump b.GenerateVtableForBase(RD); 1147bf595a3b1f1737eb60203856ea34b759c4c09c46Mike Stump b.GenerateVtableForVBases(RD); 1148f0070dbae9535836ad41711081465dec2259786bMike Stump register_index(RD, b.getIndex()); 1149f0070dbae9535836ad41711081465dec2259786bMike Stump I = IndexFor.find(RD); 1150f0070dbae9535836ad41711081465dec2259786bMike Stump } 1151f0070dbae9535836ad41711081465dec2259786bMike Stump assert(I->second->find(MD)!=I->second->end() && "Can't find vtable index"); 1152f0070dbae9535836ad41711081465dec2259786bMike Stump return (*I->second)[MD]; 1153f0070dbae9535836ad41711081465dec2259786bMike Stump } 1154f0070dbae9535836ad41711081465dec2259786bMike Stump}; 1155f0070dbae9535836ad41711081465dec2259786bMike Stump 1156f0070dbae9535836ad41711081465dec2259786bMike Stump// FIXME: Move to Context. 1157f0070dbae9535836ad41711081465dec2259786bMike StumpVtableInfo::MapTy VtableInfo::IndexFor; 1158f0070dbae9535836ad41711081465dec2259786bMike Stump 1159f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stumpllvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { 1160f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::SmallString<256> OutName; 1161f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::raw_svector_ostream Out(OutName); 1162f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump QualType ClassTy; 1163e607ed068334bacb8d7b093996b4671c6ca79e25Mike Stump ClassTy = getContext().getTagDeclType(RD); 1164f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump mangleCXXVtable(ClassTy, getContext(), Out); 116582b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::GlobalVariable::LinkageTypes linktype; 116682b56961dcb813674dbda3c5f5aaee703d55741cMike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 116782b56961dcb813674dbda3c5f5aaee703d55741cMike Stump std::vector<llvm::Constant *> methods; 1168276b9f1d814f4f6551cc3000590759a34185d6daMike Stump llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 116998cc71003d385561224e3711cd34c5b03f27ccdcMike Stump int64_t AddressPoint; 11706f376336138ea719e3c4757ae046a5768043b276Mike Stump 1171eb7e9c39f3b8ac815a78003992f2c2c662c0ab52Mike Stump VtableBuilder b(methods, RD, CGM); 1172109b13db3391face0b393c730f0326ca51d25b52Mike Stump 1173276b9f1d814f4f6551cc3000590759a34185d6daMike Stump // First comes the vtables for all the non-virtual bases... 117498cc71003d385561224e3711cd34c5b03f27ccdcMike Stump AddressPoint = b.GenerateVtableForBase(RD); 117570101ce87ff1d73ac90e4d99a3af0ae509e5934fMike Stump 1176276b9f1d814f4f6551cc3000590759a34185d6daMike Stump // then the vtables for all the virtual bases. 1177bf595a3b1f1737eb60203856ea34b759c4c09c46Mike Stump b.GenerateVtableForVBases(RD); 11786f376336138ea719e3c4757ae046a5768043b276Mike Stump 117982b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::Constant *C; 118082b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size()); 118182b56961dcb813674dbda3c5f5aaee703d55741cMike Stump C = llvm::ConstantArray::get(type, methods); 118282b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::Value *vtable = new llvm::GlobalVariable(CGM.getModule(), type, true, 11837765934ad7e157b5fcf925792a38e01b1edbcf8aDaniel Dunbar linktype, C, Out.str()); 1184f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump vtable = Builder.CreateBitCast(vtable, Ptr8Ty); 1185f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump vtable = Builder.CreateGEP(vtable, 1186276b9f1d814f4f6551cc3000590759a34185d6daMike Stump llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 118798cc71003d385561224e3711cd34c5b03f27ccdcMike Stump AddressPoint*LLVMPointerWidth/8)); 1188f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump return vtable; 1189f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump} 1190f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump 1191f0070dbae9535836ad41711081465dec2259786bMike Stump// FIXME: move to Context 1192f0070dbae9535836ad41711081465dec2259786bMike Stumpstatic VtableInfo *vtableinfo; 1193f0070dbae9535836ad41711081465dec2259786bMike Stump 1194ed032eb5c18b99528cbd76415337b6056a72b911Mike Stumpllvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn, 1195ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump const CXXMethodDecl *MD, 119677ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump bool Extern, int64_t nv, 119777ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t v) { 1198ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump QualType R = MD->getType()->getAsFunctionType()->getResultType(); 1199ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 1200ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FunctionArgList Args; 1201ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ImplicitParamDecl *ThisDecl = 1202ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 1203ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump MD->getThisType(getContext())); 1204ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); 1205ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump for (FunctionDecl::param_const_iterator i = MD->param_begin(), 1206ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump e = MD->param_end(); 1207ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump i != e; ++i) { 1208ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ParmVarDecl *D = *i; 1209ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump Args.push_back(std::make_pair(D, D->getType())); 1210ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump } 1211ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump IdentifierInfo *II 1212ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump = &CGM.getContext().Idents.get("__thunk_named_foo_"); 1213ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FunctionDecl *FD = FunctionDecl::Create(getContext(), 1214ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump getContext().getTranslationUnitDecl(), 1215ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump SourceLocation(), II, R, 0, 1216ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump Extern 1217ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump ? FunctionDecl::Extern 1218ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump : FunctionDecl::Static, 1219ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump false, true); 1220ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump StartFunction(FD, R, Fn, Args, SourceLocation()); 1221ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump // FIXME: generate body 1222ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FinishFunction(); 1223ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump return Fn; 1224ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump} 1225ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 12266e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stumpllvm::Constant *CodeGenFunction::GenerateCovariantThunk(llvm::Function *Fn, 12276e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump const CXXMethodDecl *MD, 12286e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump bool Extern, 12296e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t nv_t, 12306e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_t, 12316e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t nv_r, 12326e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_r) { 12336e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump QualType R = MD->getType()->getAsFunctionType()->getResultType(); 12346e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 12356e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FunctionArgList Args; 12366e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ImplicitParamDecl *ThisDecl = 12376e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, 12386e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump MD->getThisType(getContext())); 12396e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Args.push_back(std::make_pair(ThisDecl, ThisDecl->getType())); 12406e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump for (FunctionDecl::param_const_iterator i = MD->param_begin(), 12416e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump e = MD->param_end(); 12426e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump i != e; ++i) { 12436e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ParmVarDecl *D = *i; 12446e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Args.push_back(std::make_pair(D, D->getType())); 12456e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump } 12466e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump IdentifierInfo *II 12476e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump = &CGM.getContext().Idents.get("__thunk_named_foo_"); 12486e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FunctionDecl *FD = FunctionDecl::Create(getContext(), 12496e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump getContext().getTranslationUnitDecl(), 12506e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump SourceLocation(), II, R, 0, 12516e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump Extern 12526e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump ? FunctionDecl::Extern 12536e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump : FunctionDecl::Static, 12546e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump false, true); 12556e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump StartFunction(FD, R, Fn, Args, SourceLocation()); 12566e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // FIXME: generate body 12576e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FinishFunction(); 12586e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump return Fn; 12596e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump} 12606e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 126177ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stumpllvm::Constant *CodeGenModule::BuildThunk(const CXXMethodDecl *MD, bool Extern, 126277ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump int64_t nv, int64_t v) { 1263ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::SmallString<256> OutName; 1264ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::raw_svector_ostream Out(OutName); 126577ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump mangleThunk(MD, nv, v, getContext(), Out); 1266ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::GlobalVariable::LinkageTypes linktype; 1267ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 1268ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump if (!Extern) 1269ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump linktype = llvm::GlobalValue::InternalLinkage; 1270ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 1271ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 1272ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump const llvm::FunctionType *FTy = 1273ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), 1274ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump FPT->isVariadic()); 1275ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 1276ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(), 1277ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump &getModule()); 127877ca8f6c5e666ef873066b580bf1b7fabd41d4f5Mike Stump CodeGenFunction(*this).GenerateThunk(Fn, MD, Extern, nv, v); 1279ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump // Fn = Builder.CreateBitCast(Fn, Ptr8Ty); 1280ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); 1281ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump return m; 1282ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump} 1283ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump 12846e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stumpllvm::Constant *CodeGenModule::BuildCovariantThunk(const CXXMethodDecl *MD, 12856e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump bool Extern, int64_t nv_t, 12866e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_t, int64_t nv_r, 12876e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump int64_t v_r) { 12886e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::SmallString<256> OutName; 12896e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::raw_svector_ostream Out(OutName); 12906e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump mangleCovariantThunk(MD, nv_t, v_t, nv_r, v_r, getContext(), Out); 12916e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::GlobalVariable::LinkageTypes linktype; 12926e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 12936e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump if (!Extern) 12946e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump linktype = llvm::GlobalValue::InternalLinkage; 12956e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::Type *Ptr8Ty=llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext),0); 12966e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 12976e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump const llvm::FunctionType *FTy = 12986e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump getTypes().GetFunctionType(getTypes().getFunctionInfo(MD), 12996e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump FPT->isVariadic()); 13006e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 13016e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::Function *Fn = llvm::Function::Create(FTy, linktype, Out.str(), 13026e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump &getModule()); 13036e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump CodeGenFunction(*this).GenerateCovariantThunk(Fn, MD, Extern, nv_t, v_t, nv_r, 13046e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump v_r); 13056e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump // Fn = Builder.CreateBitCast(Fn, Ptr8Ty); 13066e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); 13076e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump return m; 13086e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump} 13096e319f6adc2a06c31cf99265854eef1321bcecf2Mike Stump 1310f0070dbae9535836ad41711081465dec2259786bMike Stumpllvm::Value * 1311f0070dbae9535836ad41711081465dec2259786bMike StumpCodeGenFunction::BuildVirtualCall(const CXXMethodDecl *MD, llvm::Value *&This, 1312f0070dbae9535836ad41711081465dec2259786bMike Stump const llvm::Type *Ty) { 1313f0070dbae9535836ad41711081465dec2259786bMike Stump // FIXME: If we know the dynamic type, we don't have to do a virtual dispatch. 13141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1315f0070dbae9535836ad41711081465dec2259786bMike Stump // FIXME: move to Context 1316f0070dbae9535836ad41711081465dec2259786bMike Stump if (vtableinfo == 0) 1317f0070dbae9535836ad41711081465dec2259786bMike Stump vtableinfo = new VtableInfo(CGM); 1318f0070dbae9535836ad41711081465dec2259786bMike Stump 1319f0070dbae9535836ad41711081465dec2259786bMike Stump VtableInfo::Index_t Idx = vtableinfo->lookup(MD); 1320f0070dbae9535836ad41711081465dec2259786bMike Stump 1321f0070dbae9535836ad41711081465dec2259786bMike Stump Ty = llvm::PointerType::get(Ty, 0); 1322f0070dbae9535836ad41711081465dec2259786bMike Stump Ty = llvm::PointerType::get(Ty, 0); 1323f0070dbae9535836ad41711081465dec2259786bMike Stump Ty = llvm::PointerType::get(Ty, 0); 1324f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::Value *vtbl = Builder.CreateBitCast(This, Ty); 1325f0070dbae9535836ad41711081465dec2259786bMike Stump vtbl = Builder.CreateLoad(vtbl); 1326f0070dbae9535836ad41711081465dec2259786bMike Stump llvm::Value *vfn = Builder.CreateConstInBoundsGEP1_64(vtbl, 1327f0070dbae9535836ad41711081465dec2259786bMike Stump Idx, "vfn"); 1328f0070dbae9535836ad41711081465dec2259786bMike Stump vfn = Builder.CreateLoad(vfn); 1329f0070dbae9535836ad41711081465dec2259786bMike Stump return vfn; 1330f0070dbae9535836ad41711081465dec2259786bMike Stump} 1331f0070dbae9535836ad41711081465dec2259786bMike Stump 1332eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// EmitClassAggrMemberwiseCopy - This routine generates code to copy a class 1333eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// array of objects from SrcValue to DestValue. Copying can be either a bitwise 1334eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// copy or via a copy constructor call. 13354f68d537c3f072366b25f3137f052eee36fddfcdFariborz Jahanian// FIXME. Consolidate this with EmitCXXAggrConstructorCall. 13361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitClassAggrMemberwiseCopy(llvm::Value *Dest, 1337eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *Src, 1338eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian const ArrayType *Array, 13391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *BaseClassDecl, 1340eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian QualType Ty) { 1341eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); 1342eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian assert(CA && "VLA cannot be copied over"); 1343eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian bool BitwiseCopy = BaseClassDecl->hasTrivialCopyConstructor(); 13441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1345eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Create a temporary for the loop index and initialize it with 0. 1346eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), 1347eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian "loop.index"); 13481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* zeroConstant = 1349eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); 1350eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateStore(zeroConstant, IndexPtr, false); 1351eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Start the loop with a block that tests the condition. 1352eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 1353eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 13541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1355eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(CondBlock); 13561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1357eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 1358eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Generate: if (loop-index < number-of-elements fall to the loop body, 1359eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // otherwise, go to the block after the for-loop. 1360eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian uint64_t NumElements = getContext().getConstantArrayElementCount(CA); 13611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value * NumElementsPtr = 1362eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); 1363eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 13641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, 1365eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian "isless"); 1366eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // If the condition is true, execute the body. 1367eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateCondBr(IsLess, ForBody, AfterFor); 13681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1369eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(ForBody); 1370eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 1371eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Inside the loop body, emit the constructor call on the array element. 1372eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1373eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); 1374eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); 1375eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian if (BitwiseCopy) 1376eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 13771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (CXXConstructorDecl *BaseCopyCtor = 1378eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BaseClassDecl->getCopyConstructor(getContext(), 0)) { 13791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, 1380eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Ctor_Complete); 1381eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian CallArgList CallArgs; 1382eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Push the this (Dest) ptr. 1383eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1384eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BaseCopyCtor->getThisType(getContext()))); 13851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1386eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Push the Src ptr. 1387eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1388eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BaseCopyCtor->getParamDecl(0)->getType())); 13891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType ResultType = 1390eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BaseCopyCtor->getType()->getAsFunctionType()->getResultType(); 1391eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1392eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Callee, CallArgs, BaseCopyCtor); 1393eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian } 1394eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(ContinueBlock); 13951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1396eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Emit the increment of the loop counter. 1397eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); 1398eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1399eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); 1400eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateStore(NextVal, IndexPtr, false); 14011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1402eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Finally, branch back up to the condition for the next iteration. 1403eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBranch(CondBlock); 14041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1405eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian // Emit the fall-through block. 1406eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitBlock(AfterFor, true); 1407eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian} 1408eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian 1409c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian/// EmitClassAggrCopyAssignment - This routine generates code to assign a class 14101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// array of objects from SrcValue to DestValue. Assignment can be either a 1411c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian/// bitwise assignment or via a copy assignment operator function call. 1412c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian/// FIXME. This can be consolidated with EmitClassAggrMemberwiseCopy 14131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest, 1414c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *Src, 1415c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const ArrayType *Array, 14161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *BaseClassDecl, 1417c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian QualType Ty) { 1418c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); 1419c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian assert(CA && "VLA cannot be asssigned"); 1420c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian bool BitwiseAssign = BaseClassDecl->hasTrivialCopyAssignment(); 14211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1422c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Create a temporary for the loop index and initialize it with 0. 1423c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *IndexPtr = CreateTempAlloca(llvm::Type::getInt64Ty(VMContext), 1424c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian "loop.index"); 14251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value* zeroConstant = 1426c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Constant::getNullValue(llvm::Type::getInt64Ty(VMContext)); 1427c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateStore(zeroConstant, IndexPtr, false); 1428c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Start the loop with a block that tests the condition. 1429c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); 1430c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); 14311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1432c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(CondBlock); 14331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1434c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *ForBody = createBasicBlock("for.body"); 1435c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Generate: if (loop-index < number-of-elements fall to the loop body, 1436c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // otherwise, go to the block after the for-loop. 1437c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian uint64_t NumElements = getContext().getConstantArrayElementCount(CA); 14381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value * NumElementsPtr = 1439c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), NumElements); 1440c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *Counter = Builder.CreateLoad(IndexPtr); 14411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElementsPtr, 1442c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian "isless"); 1443c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // If the condition is true, execute the body. 1444c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateCondBr(IsLess, ForBody, AfterFor); 14451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1446c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(ForBody); 1447c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); 1448c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Inside the loop body, emit the assignment operator call on array element. 1449c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1450c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Src = Builder.CreateInBoundsGEP(Src, Counter, "srcaddress"); 1451c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Dest = Builder.CreateInBoundsGEP(Dest, Counter, "destaddress"); 1452c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const CXXMethodDecl *MD = 0; 1453c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian if (BitwiseAssign) 1454c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 1455c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian else { 1456c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian bool hasCopyAssign = BaseClassDecl->hasConstCopyAssignment(getContext(), 1457c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian MD); 1458c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian assert(hasCopyAssign && "EmitClassAggrCopyAssignment - No user assign"); 1459c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian (void)hasCopyAssign; 1460c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 1461c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const llvm::Type *LTy = 1462c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 1463c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian FPT->isVariadic()); 1464555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); 14651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1466c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CallArgList CallArgs; 1467c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Push the this (Dest) ptr. 1468c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1469c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian MD->getThisType(getContext()))); 14701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1471c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Push the Src ptr. 1472c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1473c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian MD->getParamDecl(0)->getType())); 1474ed032eb5c18b99528cbd76415337b6056a72b911Mike Stump QualType ResultType = MD->getType()->getAsFunctionType()->getResultType(); 1475c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1476c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Callee, CallArgs, MD); 1477c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian } 1478c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(ContinueBlock); 14791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1480c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Emit the increment of the loop counter. 1481c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); 1482c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Counter = Builder.CreateLoad(IndexPtr); 1483c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); 1484c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateStore(NextVal, IndexPtr, false); 14851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1486c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Finally, branch back up to the condition for the next iteration. 1487c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBranch(CondBlock); 14881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1489c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian // Emit the fall-through block. 1490c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitBlock(AfterFor, true); 1491c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian} 1492c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian 1493ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian/// EmitClassMemberwiseCopy - This routine generates code to copy a class 1494ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian/// object from SrcValue to DestValue. Copying can be either a bitwise copy 1495eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian/// or via a copy constructor call. 1496ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanianvoid CodeGenFunction::EmitClassMemberwiseCopy( 1497942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian llvm::Value *Dest, llvm::Value *Src, 14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *ClassDecl, 1499942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian const CXXRecordDecl *BaseClassDecl, QualType Ty) { 1500942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian if (ClassDecl) { 15015a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Dest = GetAddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl, 15025a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 15035a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Src = GetAddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl, 15045a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 1505942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian } 1506942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian if (BaseClassDecl->hasTrivialCopyConstructor()) { 1507942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 1508ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian return; 1509942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian } 15101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (CXXConstructorDecl *BaseCopyCtor = 151280e4b9e0e87064a824d72b6ff89074206ecced58Fariborz Jahanian BaseClassDecl->getCopyConstructor(getContext(), 0)) { 15131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, 1514ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian Ctor_Complete); 1515ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgList CallArgs; 1516ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian // Push the this (Dest) ptr. 1517ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1518ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian BaseCopyCtor->getThisType(getContext()))); 15191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1520ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian // Push the Src ptr. 1521ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1522370c884d172329384973e452647fba0b2f5146d5Fariborz Jahanian BaseCopyCtor->getParamDecl(0)->getType())); 15231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType ResultType = 1524ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian BaseCopyCtor->getType()->getAsFunctionType()->getResultType(); 1525ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1526ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian Callee, CallArgs, BaseCopyCtor); 1527ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian } 1528ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian} 152906f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian 15300270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// EmitClassCopyAssignment - This routine generates code to copy assign a class 15311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// object from SrcValue to DestValue. Assignment can be either a bitwise 15320270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// assignment of via an assignment operator call. 1533c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian// FIXME. Consolidate this with EmitClassMemberwiseCopy as they share a lot. 15340270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanianvoid CodeGenFunction::EmitClassCopyAssignment( 15350270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *Dest, llvm::Value *Src, 15361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *ClassDecl, 15371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const CXXRecordDecl *BaseClassDecl, 15380270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian QualType Ty) { 15390270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (ClassDecl) { 15405a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Dest = GetAddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl, 15415a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 15425a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson Src = GetAddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl, 15435a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 15440270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 15450270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (BaseClassDecl->hasTrivialCopyAssignment()) { 15460270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 15470270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian return; 15480270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 15491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15500270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const CXXMethodDecl *MD = 0; 15511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump bool ConstCopyAssignOp = BaseClassDecl->hasConstCopyAssignment(getContext(), 1552e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian MD); 1553e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian assert(ConstCopyAssignOp && "EmitClassCopyAssignment - missing copy assign"); 1554e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian (void)ConstCopyAssignOp; 1555e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian 1556e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 15571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const llvm::Type *LTy = 15581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 1559e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian FPT->isVariadic()); 1560555b4bb2749aea2ec8e2adc351a71ec1cb9bdc33Anders Carlsson llvm::Constant *Callee = CGM.GetAddrOfFunction(MD, LTy); 15611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1562e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian CallArgList CallArgs; 1563e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian // Push the this (Dest) ptr. 1564e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 1565e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian MD->getThisType(getContext()))); 15661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1567e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian // Push the Src ptr. 1568e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 1569e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian MD->getParamDecl(0)->getType())); 15701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType ResultType = 1571e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian MD->getType()->getAsFunctionType()->getResultType(); 1572e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 1573e82c3e269f0edd6d531b93114e97573792e808e0Fariborz Jahanian Callee, CallArgs, MD); 15740270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian} 15750270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian 157606f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian/// SynthesizeDefaultConstructor - synthesize a default constructor 15771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid 15780ff8bafde95f6fa51ccea70738c1b99db870bddcAnders CarlssonCodeGenFunction::SynthesizeDefaultConstructor(GlobalDecl GD, 157906f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian const FunctionDecl *FD, 158006f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian llvm::Function *Fn, 158106f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian const FunctionArgList &Args) { 15820ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(GD.getDecl()); 15830ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson 15840ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson StartFunction(GD, FD->getResultType(), Fn, Args, SourceLocation()); 15850ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson EmitCtorPrologue(Ctor); 158606f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian FinishFunction(); 158706f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian} 158806f598aa45b651f9f3be0b916d43876eae747af0Fariborz Jahanian 15898c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a copy 159097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// constructor, in accordance with section 12.8 (p7 and p8) of C++03 15911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// The implicitly-defined copy constructor for class X performs a memberwise 15921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// copy of its subobjects. The order of copying is the same as the order 159397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// of initialization of bases and members in a user-defined constructor 159497a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// Each subobject is copied in the manner appropriate to its type: 15951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of class type, the copy constructor for the class is 159697a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// used; 15971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is an array, each element is copied, in the manner 159897a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// appropriate to the element type; 15991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of scalar type, the built-in assignment operator is 160097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// used. 16011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// Virtual base class subobjects shall be copied only once by the 16021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// implicitly-defined copy constructor 160397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 16040ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlssonvoid CodeGenFunction::SynthesizeCXXCopyConstructor(GlobalDecl GD, 16058c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian const FunctionDecl *FD, 16068c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian llvm::Function *Fn, 1607ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian const FunctionArgList &Args) { 16080ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(GD.getDecl()); 16090ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson const CXXRecordDecl *ClassDecl = Ctor->getParent(); 161097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyConstructor() && 16118c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian "SynthesizeCXXCopyConstructor - copy constructor has definition already"); 16120ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson StartFunction(GD, Ctor->getResultType(), Fn, Args, SourceLocation()); 16131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16141e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian FunctionArgList::const_iterator i = Args.begin(); 16151e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian const VarDecl *ThisArg = i->first; 16161e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); 16171e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); 16181e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian const VarDecl *SrcArg = (i+1)->first; 16191e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); 16201e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); 16211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 162297a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); 162397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 162497a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian // FIXME. copy constrution of virtual base NYI 162597a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian if (Base->isVirtual()) 162697a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian continue; 16271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 162897a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian CXXRecordDecl *BaseClassDecl 162997a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 1630942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, 1631942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian Base->getType()); 163297a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian } 16331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16341e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 16351e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian FieldEnd = ClassDecl->field_end(); 16361e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian Field != FieldEnd; ++Field) { 16371e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 16381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1639eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1640eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian if (Array) 1641eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 16421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16431e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { 16441e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian CXXRecordDecl *FieldClassDecl 16451e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian = cast<CXXRecordDecl>(FieldClassType->getDecl()); 16461e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 16471e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 1648eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian if (Array) { 1649eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1650eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 16511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *DestBaseAddrPtr = 1652eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 16531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *SrcBaseAddrPtr = 1654eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian Builder.CreateBitCast(RHS.getAddress(), BasePtr); 1655eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian EmitClassAggrMemberwiseCopy(DestBaseAddrPtr, SrcBaseAddrPtr, Array, 1656eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian FieldClassDecl, FieldType); 1657eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian } 16581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 16591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), 1660eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian 0 /*ClassDecl*/, FieldClassDecl, FieldType); 16611e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian continue; 16621e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian } 1663f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian // Do a built-in assignment of scalar data members. 1664f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 1665f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 1666f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian RValue RVRHS = EmitLoadOfLValue(RHS, FieldType); 1667f05fe65e64a5de93ba6d30e1b830fd0fc36358e9Fariborz Jahanian EmitStoreThroughLValue(RVRHS, LHS, FieldType); 16681e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian } 16698c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian FinishFunction(); 16701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 167197a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 16722198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// SynthesizeCXXCopyAssignment - Implicitly define copy assignment operator. 16731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// Before the implicitly-declared copy assignment operator for a class is 16741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// implicitly defined, all implicitly- declared copy assignment operators for 16751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// its direct base classes and its nonstatic data members shall have been 16762198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// implicitly defined. [12.8-p12] 16771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// The implicitly-defined copy assignment operator for class X performs 16781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// memberwise assignment of its subob- jects. The direct base classes of X are 16791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// assigned first, in the order of their declaration in 16801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// the base-specifier-list, and then the immediate nonstatic data members of X 16811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// are assigned, in the order in which they were declared in the class 16822198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// definition.Each subobject is assigned in the manner appropriate to its type: 16831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of class type, the copy assignment operator for the 16841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// class is used (as if by explicit qualification; that is, ignoring any 16852198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// possible virtual overriding functions in more derived classes); 16860270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// 16871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is an array, each element is assigned, in the manner 16882198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// appropriate to the element type; 16890270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian/// 16901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if the subobject is of scalar type, the built-in assignment operator is 16912198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian/// used. 16922198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanianvoid CodeGenFunction::SynthesizeCXXCopyAssignment(const CXXMethodDecl *CD, 16932198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian const FunctionDecl *FD, 16942198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian llvm::Function *Fn, 16952198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian const FunctionArgList &Args) { 16960270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian 16970270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); 16980270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyAssignment() && 16990270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian "SynthesizeCXXCopyAssignment - copy assignment has user declaration"); 17002198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian StartFunction(FD, FD->getResultType(), Fn, Args, SourceLocation()); 17011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17020270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian FunctionArgList::const_iterator i = Args.begin(); 17030270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const VarDecl *ThisArg = i->first; 17040270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); 17050270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); 17060270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian const VarDecl *SrcArg = (i+1)->first; 17070270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); 17080270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); 17091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17100270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); 17110270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 17120270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian // FIXME. copy assignment of virtual base NYI 17130270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (Base->isVirtual()) 17140270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian continue; 17151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17160270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian CXXRecordDecl *BaseClassDecl 17170270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 17180270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian EmitClassCopyAssignment(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, 17190270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian Base->getType()); 17200270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 17211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17220270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 17230270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian FieldEnd = ClassDecl->field_end(); 17240270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian Field != FieldEnd; ++Field) { 17250270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 17261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1727c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1728c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian if (Array) 1729c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 17301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17310270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { 17320270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian CXXRecordDecl *FieldClassDecl 17330270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian = cast<CXXRecordDecl>(FieldClassType->getDecl()); 17340270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 17350270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 1736c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian if (Array) { 1737c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1738c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 1739c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *DestBaseAddrPtr = 1740c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 1741c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian llvm::Value *SrcBaseAddrPtr = 1742c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian Builder.CreateBitCast(RHS.getAddress(), BasePtr); 1743c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian EmitClassAggrCopyAssignment(DestBaseAddrPtr, SrcBaseAddrPtr, Array, 1744c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian FieldClassDecl, FieldType); 1745c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian } 1746c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian else 17471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitClassCopyAssignment(LHS.getAddress(), RHS.getAddress(), 1748c28bbc2d2271aab6c5d79ef2758604221cd92a4bFariborz Jahanian 0 /*ClassDecl*/, FieldClassDecl, FieldType); 17490270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian continue; 17500270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian } 17510270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian // Do a built-in assignment of scalar data members. 17520270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 17530270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 17540270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian RValue RVRHS = EmitLoadOfLValue(RHS, FieldType); 17550270b8aa3f9b50ec3acd1abfd2b97377a3e1bb05Fariborz Jahanian EmitStoreThroughLValue(RVRHS, LHS, FieldType); 1756183d7181fd59842ac969cbc6fe0376f85dc63ae4Fariborz Jahanian } 17571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1758183d7181fd59842ac969cbc6fe0376f85dc63ae4Fariborz Jahanian // return *this; 1759183d7181fd59842ac969cbc6fe0376f85dc63ae4Fariborz Jahanian Builder.CreateStore(LoadOfThis, ReturnValue); 17601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17612198ba12b73a8e6801d13f25de38031da6df46b6Fariborz Jahanian FinishFunction(); 17621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 176397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 1764e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian/// EmitCtorPrologue - This routine generates necessary code to initialize 1765e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian/// base classes and non-static data members belonging to this constructor. 1766174754cda4596f3bb2539df61ab2ab7a17aad6bfAnders Carlsson/// FIXME: This needs to take a CXXCtorType. 1767e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanianvoid CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { 1768742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); 1769eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump // FIXME: Add vbase initialization 1770f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *LoadOfThis = 0; 17711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1772742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), 1773e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian E = CD->init_end(); 1774e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian B != E; ++B) { 1775e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian CXXBaseOrMemberInitializer *Member = (*B); 1776e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian if (Member->isBaseInitializer()) { 1777f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 17786d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian Type *BaseType = Member->getBaseClass(); 17791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CXXRecordDecl *BaseClassDecl = 17806217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); 17815a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl, 17825a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson BaseClassDecl, 17835a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 1784742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian EmitCXXConstructorCall(Member->getConstructor(), 1785742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian Ctor_Complete, V, 17861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Member->const_arg_begin(), 1787742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian Member->const_arg_end()); 1788b3589f44c5d295cd41de2c83f3475116835eeebdMike Stump } else { 1789e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian // non-static data member initilaizers. 1790e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian FieldDecl *Field = Member->getMember(); 1791e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian QualType FieldType = getContext().getCanonicalType((Field)->getType()); 17921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1793eb0b6d556ff2b4a5053e89fd084eb34e44cea14cFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 179464a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian if (Array) 179564a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 17961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1797f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 1798e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman LValue LHS; 1799e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman if (FieldType->isReferenceType()) { 1800e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman // FIXME: This is really ugly; should be refactored somehow 1801e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman unsigned idx = CGM.getTypes().getLLVMFieldNo(Field); 1802e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman llvm::Value *V = Builder.CreateStructGEP(LoadOfThis, idx, "tmp"); 1803e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman LHS = LValue::MakeAddr(V, FieldType.getCVRQualifiers(), 1804e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman QualType::GCNone, FieldType.getAddressSpace()); 1805e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman } else { 1806e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman LHS = EmitLValueForField(LoadOfThis, Field, false, 0); 1807e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman } 18086217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (FieldType->getAs<RecordType>()) { 1809e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian if (!Field->isAnonymousStructOrUnion()) { 18101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(Member->getConstructor() && 181150b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian "EmitCtorPrologue - no constructor to initialize member"); 181264a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian if (Array) { 181364a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 181464a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 18151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 181664a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 18171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXAggrConstructorCall(Member->getConstructor(), 181864a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Array, BaseAddrPtr); 181964a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian } 182064a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian else 182164a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian EmitCXXConstructorCall(Member->getConstructor(), 182264a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Ctor_Complete, LHS.getAddress(), 18231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Member->const_arg_begin(), 182464a54ad29929443006d4c8502173c163bedaa223Fariborz Jahanian Member->const_arg_end()); 1825e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian continue; 1826e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian } 1827e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian else { 1828e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian // Initializing an anonymous union data member. 1829e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian FieldDecl *anonMember = Member->getAnonUnionMember(); 18301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump LHS = EmitLValueForField(LHS.getAddress(), anonMember, 1831c186b8fe4a308b53569fe839a3224de70d92ab0eAnders Carlsson /*IsUnion=*/true, 0); 1832e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian FieldType = anonMember->getType(); 1833e64941280877d065a27e8cefd2a9038256d0e3acFariborz Jahanian } 183450b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian } 18351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1836e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only"); 183750b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian Expr *RhsExpr = *Member->arg_begin(); 1838e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman RValue RHS; 1839e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman if (FieldType->isReferenceType()) 1840e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman RHS = EmitReferenceBindingToExpr(RhsExpr, FieldType, 1841e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman /*IsInitializer=*/true); 1842e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman else 1843e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman RHS = RValue::get(EmitScalarExpr(RhsExpr, true)); 1844e3a97db45ac46adf963115d0266cfd3e6bc2dce8Eli Friedman EmitStoreThroughLValue(RHS, LHS, FieldType); 1845e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian } 1846e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian } 1847f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump 18480880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (!CD->getNumBaseOrMemberInitializers() && !CD->isTrivial()) { 18491d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian // Nontrivial default constructor with no initializer list. It may still 18501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // have bases classes and/or contain non-static data members which require 18510880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // construction. 18521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (CXXRecordDecl::base_class_const_iterator Base = 18530880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian ClassDecl->bases_begin(); 18540880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 18550880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // FIXME. copy assignment of virtual base NYI 18560880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (Base->isVirtual()) 18570880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 18581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18590880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *BaseClassDecl 18600880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 18610880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (BaseClassDecl->hasTrivialConstructor()) 18620880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 18631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (CXXConstructorDecl *BaseCX = 18640880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian BaseClassDecl->getDefaultConstructor(getContext())) { 18650880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LoadOfThis = LoadCXXThis(); 18665a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadOfThis, ClassDecl, 18675a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson BaseClassDecl, 18685a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 18690880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian EmitCXXConstructorCall(BaseCX, Ctor_Complete, V, 0, 0); 18700880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 18710880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 18721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18731d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 18741d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian FieldEnd = ClassDecl->field_end(); 18751d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian Field != FieldEnd; ++Field) { 18761d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 18771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1878288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1879f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) 1880f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 18811d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian if (!FieldType->getAs<RecordType>() || Field->isAnonymousStructOrUnion()) 18821d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian continue; 18831d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian const RecordType *ClassRec = FieldType->getAs<RecordType>(); 18841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CXXRecordDecl *MemberClassDecl = 18850880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian dyn_cast<CXXRecordDecl>(ClassRec->getDecl()); 18860880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (!MemberClassDecl || MemberClassDecl->hasTrivialConstructor()) 18870880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 18881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (CXXConstructorDecl *MamberCX = 18890880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian MemberClassDecl->getDefaultConstructor(getContext())) { 18900880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LoadOfThis = LoadCXXThis(); 18910880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 1892288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian if (Array) { 1893288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1894288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 18951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 1896288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 1897288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian EmitCXXAggrConstructorCall(MamberCX, Array, BaseAddrPtr); 1898288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian } 1899288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian else 19001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXConstructorCall(MamberCX, Ctor_Complete, LHS.getAddress(), 1901288dcaf329c49b01dacd5c1dd9f35609555feecdFariborz Jahanian 0, 0); 19021d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian } 19031d9b5efffaec2349f33510dee2cf2e90c3d2d6aaFariborz Jahanian } 19040880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 19051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1906f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump // Initialize the vtable pointer 1907b502d839994cc3828573bd9ea472418e3536f415Mike Stump if (ClassDecl->isDynamicClass()) { 1908f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump if (!LoadOfThis) 1909f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 1910f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *VtableField; 1911f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Type *Ptr8Ty, *PtrPtr8Ty; 19120032b2781b4deb131f8c9b7968f2030bf2489cddOwen Anderson Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 1913f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0); 1914f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump VtableField = Builder.CreateBitCast(LoadOfThis, PtrPtr8Ty); 1915f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *vtable = GenerateVtable(ClassDecl); 1916f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump Builder.CreateStore(vtable, VtableField); 1917f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump } 1918e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian} 1919426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian 1920426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian/// EmitDtorEpilogue - Emit all code that comes at the end of class's 19211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// destructor. This is to call destructors on members and base classes 1922426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian/// in reverse order of their construction. 1923174754cda4596f3bb2539df61ab2ab7a17aad6bfAnders Carlsson/// FIXME: This needs to take a CXXDtorType. 1924426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanianvoid CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD) { 1925426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext()); 1926de738fe899b5c1d387dbc66a1122032e694d3d6fAnders Carlsson assert(!ClassDecl->getNumVBases() && 1927de738fe899b5c1d387dbc66a1122032e694d3d6fAnders Carlsson "FIXME: Destruction of virtual bases not supported"); 1928426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian (void)ClassDecl; // prevent warning. 19291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1930426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(), 1931426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian *E = DD->destr_end(); B != E; ++B) { 1932426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian uintptr_t BaseOrMember = (*B); 1933426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (DD->isMemberToDestroy(BaseOrMember)) { 1934426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember); 1935426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian QualType FieldType = getContext().getCanonicalType((FD)->getType()); 19361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1937f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1938f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) 1939f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 1940426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const RecordType *RT = FieldType->getAs<RecordType>(); 1941426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 1942426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (FieldClassDecl->hasTrivialDestructor()) 1943426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian continue; 1944426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian llvm::Value *LoadOfThis = LoadCXXThis(); 1945426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0); 1946f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) { 1947f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 1948f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 19491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 1950f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 19511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), 1952f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Array, BaseAddrPtr); 1953f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian } 1954f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian else 1955f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), 1956f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Dtor_Complete, LHS.getAddress()); 1957b3589f44c5d295cd41de2c83f3475116835eeebdMike Stump } else { 1958426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const RecordType *RT = 1959426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs<RecordType>(); 1960426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 1961426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (BaseClassDecl->hasTrivialDestructor()) 1962426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian continue; 19635a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(), 19645a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson ClassDecl, BaseClassDecl, 19655a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 1966426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), 1967426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian Dtor_Complete, V); 1968426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian } 1969426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian } 19700880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (DD->getNumBaseOrMemberDestructions() || DD->isTrivial()) 19710880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian return; 19720880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // Case of destructor synthesis with fields and base classes 19731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // which have non-trivial destructors. They must be destructed in 19740880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // reverse order of their construction. 19750880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::SmallVector<FieldDecl *, 16> DestructedFields; 19761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19770880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 19780880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian FieldEnd = ClassDecl->field_end(); 19790880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Field != FieldEnd; ++Field) { 19800880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 1981f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (getContext().getAsConstantArrayType(FieldType)) 1982f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 19830880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (const RecordType *RT = FieldType->getAs<RecordType>()) { 19840880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 19850880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (FieldClassDecl->hasTrivialDestructor()) 19860880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 19870880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian DestructedFields.push_back(*Field); 19880880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 19890880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 19900880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (!DestructedFields.empty()) 19910880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (int i = DestructedFields.size() -1; i >= 0; --i) { 19920880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian FieldDecl *Field = DestructedFields[i]; 19930880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian QualType FieldType = Field->getType(); 19941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const ConstantArrayType *Array = 1995f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian getContext().getAsConstantArrayType(FieldType); 1996f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) 1997f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian FieldType = getContext().getBaseElementType(FieldType); 19980880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian const RecordType *RT = FieldType->getAs<RecordType>(); 19990880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 20000880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::Value *LoadOfThis = LoadCXXThis(); 20010880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); 2002f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian if (Array) { 2003f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian const llvm::Type *BasePtr = ConvertType(FieldType); 2004f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian BasePtr = llvm::PointerType::getUnqual(BasePtr); 20051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::Value *BaseAddrPtr = 2006f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Builder.CreateBitCast(LHS.getAddress(), BasePtr); 20071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), 2008f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Array, BaseAddrPtr); 2009f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian } 2010f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian else 2011f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), 2012f800f6c09ed4a71bcb593d6962e0fda2c2845a70Fariborz Jahanian Dtor_Complete, LHS.getAddress()); 20130880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 20141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20150880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::SmallVector<CXXRecordDecl*, 4> DestructedBases; 20160880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); 20170880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 20180880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian // FIXME. copy assignment of virtual base NYI 20190880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (Base->isVirtual()) 20200880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 20211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20220880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *BaseClassDecl 20230880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 20240880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (BaseClassDecl->hasTrivialDestructor()) 20250880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian continue; 20260880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian DestructedBases.push_back(BaseClassDecl); 20270880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 20280880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian if (DestructedBases.empty()) 20290880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian return; 20300880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian for (int i = DestructedBases.size() -1; i >= 0; --i) { 20310880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian CXXRecordDecl *BaseClassDecl = DestructedBases[i]; 20325a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson llvm::Value *V = GetAddressCXXOfBaseClass(LoadCXXThis(), 20335a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson ClassDecl,BaseClassDecl, 20345a0f49ebc83e7fe0da07b9964c44b0a7fae270cbAnders Carlsson /*NullCheckValue=*/false); 20350880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), 20360880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian Dtor_Complete, V); 20370880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian } 2038426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian} 20390880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian 20400ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlssonvoid CodeGenFunction::SynthesizeDefaultDestructor(GlobalDecl GD, 20410880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian const FunctionDecl *FD, 20420880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian llvm::Function *Fn, 20430880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian const FunctionArgList &Args) { 20441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20450ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(GD.getDecl()); 20460ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson 20470ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson const CXXRecordDecl *ClassDecl = Dtor->getParent(); 20480880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian assert(!ClassDecl->hasUserDeclaredDestructor() && 20490880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian "SynthesizeDefaultDestructor - destructor has user declaration"); 20500880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian (void) ClassDecl; 20511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20520ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson StartFunction(GD, Dtor->getResultType(), Fn, Args, SourceLocation()); 20530ff8bafde95f6fa51ccea70738c1b99db870bddcAnders Carlsson EmitDtorEpilogue(Dtor); 20540880bacf8fdb7de9d9c5b53b81ea0e53afccafb5Fariborz Jahanian FinishFunction(); 20551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 2056