CGCXX.cpp revision 942f4f33d02dba823594bd2d7b3d317cb01c74f8
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 14e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson// 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 280096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbarvoid 293b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders CarlssonCodeGenFunction::EmitCXXGlobalDtorRegistration(const CXXDestructorDecl *Dtor, 303b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DeclPtr) { 313b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // FIXME: This is ABI dependent and we use the Itanium ABI. 323b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 333b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson const llvm::Type *Int8PtrTy = 343b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 353b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 363b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson std::vector<const llvm::Type *> Params; 373b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 383b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 393b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // Get the destructor function type 403b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson const llvm::Type *DtorFnTy = 413b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::FunctionType::get(llvm::Type::VoidTy, Params, false); 423b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson DtorFnTy = llvm::PointerType::getUnqual(DtorFnTy); 433b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 443b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.clear(); 453b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(DtorFnTy); 463b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 473b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson Params.push_back(Int8PtrTy); 483b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 493b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // Get the __cxa_atexit function type 503b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson // extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d ); 513b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson const llvm::FunctionType *AtExitFnTy = 523b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::FunctionType::get(ConvertType(getContext().IntTy), Params, false); 533b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 543b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *AtExitFn = CGM.CreateRuntimeFunction(AtExitFnTy, 553b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "__cxa_atexit"); 563b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 573b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *Handle = CGM.CreateRuntimeVariable(Int8PtrTy, 583b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "__dso_handle"); 593b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 603b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DtorFn = CGM.GetAddrOfCXXDestructor(Dtor, Dtor_Complete); 613b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 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 683b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlssonvoid CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, 693b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson llvm::Constant *DeclPtr) { 703b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson assert(D.hasGlobalStorage() && 713b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson "VarDecl must have global storage!"); 723b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 733b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson const Expr *Init = D.getInit(); 743b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson QualType T = D.getType(); 753b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 763b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson if (T->isReferenceType()) { 773b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders 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()); 853b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 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; 9889ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 9989ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson const llvm::FunctionType *FTy = llvm::FunctionType::get(llvm::Type::VoidTy, 10089ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson false); 10189ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 10289ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson // Create our global initialization function. 10389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson // FIXME: Should this be tweakable by targets? 10489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson llvm::Function *Fn = 10589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, 10689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson "__cxx_global_initialization", &TheModule); 10789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 10889ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, 10989ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson CXXGlobalInits.data(), 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) { 11789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson StartFunction(0, getContext().VoidTy, Fn, FunctionArgList(), 11889ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson SourceLocation()); 11989ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 12089ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson for (unsigned i = 0; i != NumDecls; ++i) { 12189ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson const VarDecl *D = Decls[i]; 12289ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 12389ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson llvm::Constant *DeclPtr = CGM.GetAddrOfGlobalVar(D); 12489ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson EmitCXXGlobalVarDeclInit(*D, DeclPtr); 12589ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson } 12689ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson FinishFunction(); 12789ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson} 12889ed31d3f9eeb8ec77c284a5cf404a74bf5e7acfAnders Carlsson 1293b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlssonvoid 1303b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders CarlssonCodeGenFunction::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); 140283a062a633d6e868aa2be319da812341fe73728Anders Carlsson 141e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Create the guard variable. 142e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson llvm::GlobalValue *GuardV = 1431c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson new llvm::GlobalVariable(CGM.getModule(), llvm::Type::Int64Ty, false, 1440096acf421c4609ce7f43e8b05f8c5ca866d4611Daniel Dunbar GV->getLinkage(), 145c9c88b4159791c48e486ca94e3743b5979e2b7a6Owen Anderson llvm::Constant::getNullValue(llvm::Type::Int64Ty), 1461c431b323d776362490bbf7cc796b74fedaf19f2Owen Anderson GuardVName.c_str()); 147e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 148e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Load the first byte of the guard variable. 14996e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson const llvm::Type *PtrTy = llvm::PointerType::get(llvm::Type::Int8Ty, 0); 150e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson llvm::Value *V = Builder.CreateLoad(Builder.CreateBitCast(GuardV, PtrTy), 151e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson "tmp"); 152e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 153e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson // Compare it against 0. 154c9c88b4159791c48e486ca94e3743b5979e2b7a6Owen Anderson llvm::Value *nullValue = llvm::Constant::getNullValue(llvm::Type::Int8Ty); 155e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson llvm::Value *ICmp = Builder.CreateICmpEQ(V, nullValue , "tobool"); 156e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 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); 162e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 163e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson EmitBlock(InitBlock); 164e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 1653b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson EmitCXXGlobalVarDeclInit(D, GV); 1663b2e16b3d25f6b311dba2871e2a566c96238c3d2Anders Carlsson 1674a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson Builder.CreateStore(llvm::ConstantInt::get(llvm::Type::Int8Ty, 1), 168e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson Builder.CreateBitCast(GuardV, PtrTy)); 169e1b29efab32d02e114046d33cca242a88585bf8aAnders Carlsson 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) { 178774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson assert(MD->isInstance() && 179774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson "Trying to emit a member call expr on a static method!"); 180b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 181b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 182b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 183b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CallArgList Args; 184b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 185b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson // Push the this ptr. 186b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson Args.push_back(std::make_pair(RValue::get(This), 187b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson MD->getThisType(getContext()))); 188b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 189b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson // And the rest of the call args 190b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); 191774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson 192b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson QualType ResultType = MD->getType()->getAsFunctionType()->getResultType(); 193b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), 194b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson Callee, Args, MD); 195b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson} 196b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 197b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders CarlssonRValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { 198b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()); 199b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); 200b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 201e9918d2443ad524e0f488e8f15d9bce4e7373cd1Anders Carlsson const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 2027116da1efe23f90eb22524ac9aa036153b74f482Mike Stump 203f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump if (MD->isVirtual()) { 2047116da1efe23f90eb22524ac9aa036153b74f482Mike Stump ErrorUnsupported(CE, "virtual dispatch"); 2057116da1efe23f90eb22524ac9aa036153b74f482Mike Stump } 2067116da1efe23f90eb22524ac9aa036153b74f482Mike Stump 207774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson const llvm::Type *Ty = 208e9918d2443ad524e0f488e8f15d9bce4e7373cd1Anders Carlsson CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 209e9918d2443ad524e0f488e8f15d9bce4e7373cd1Anders Carlsson FPT->isVariadic()); 210b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty); 211774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson 212b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *This; 213774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson 214774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson if (ME->isArrow()) 215b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson This = EmitScalarExpr(ME->getBase()); 216774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson else { 217774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson LValue BaseLV = EmitLValue(ME->getBase()); 218b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson This = BaseLV.getAddress(); 219774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson } 220774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson 221b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson return EmitCXXMemberCall(MD, Callee, This, 222b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson CE->arg_begin(), CE->arg_end()); 223774e7c6881ee6cb970cd42239d700dce87ed402aAnders Carlsson} 2245f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson 2250f294632f36459174199b77699e339715244b5abAnders CarlssonRValue 2260f294632f36459174199b77699e339715244b5abAnders CarlssonCodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, 2270f294632f36459174199b77699e339715244b5abAnders Carlsson const CXXMethodDecl *MD) { 2280f294632f36459174199b77699e339715244b5abAnders Carlsson assert(MD->isInstance() && 2290f294632f36459174199b77699e339715244b5abAnders Carlsson "Trying to emit a member call expr on a static method!"); 2300f294632f36459174199b77699e339715244b5abAnders Carlsson 2310f294632f36459174199b77699e339715244b5abAnders Carlsson 2320f294632f36459174199b77699e339715244b5abAnders Carlsson const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType(); 2330f294632f36459174199b77699e339715244b5abAnders Carlsson const llvm::Type *Ty = 2340f294632f36459174199b77699e339715244b5abAnders Carlsson CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 2350f294632f36459174199b77699e339715244b5abAnders Carlsson FPT->isVariadic()); 2360f294632f36459174199b77699e339715244b5abAnders Carlsson llvm::Constant *Callee = CGM.GetAddrOfFunction(GlobalDecl(MD), Ty); 2370f294632f36459174199b77699e339715244b5abAnders Carlsson 2380f294632f36459174199b77699e339715244b5abAnders Carlsson llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 2390f294632f36459174199b77699e339715244b5abAnders Carlsson 2400f294632f36459174199b77699e339715244b5abAnders Carlsson return EmitCXXMemberCall(MD, Callee, This, 2410f294632f36459174199b77699e339715244b5abAnders Carlsson E->arg_begin() + 1, E->arg_end()); 2420f294632f36459174199b77699e339715244b5abAnders Carlsson} 2430f294632f36459174199b77699e339715244b5abAnders Carlsson 2445f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlssonllvm::Value *CodeGenFunction::LoadCXXThis() { 2455f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson assert(isa<CXXMethodDecl>(CurFuncDecl) && 2465f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson "Must be in a C++ member function decl to load 'this'"); 2475f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson assert(cast<CXXMethodDecl>(CurFuncDecl)->isInstance() && 2485f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson "Must be in a C++ member function decl to load 'this'"); 2495f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson 2505f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson // FIXME: What if we're inside a block? 251f5408fe484495ee4efbdd709c8a2c2fdbbbdb328Mike Stump // ans: See how CodeGenFunction::LoadObjCSelf() uses 252f5408fe484495ee4efbdd709c8a2c2fdbbbdb328Mike Stump // CodeGenFunction::BlockForwardSelf() for how to do this. 2535f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); 2545f4307b7ba164b03c853c8d3eb4674d33f8967a6Anders Carlsson} 25595d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlsson 256c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanianstatic bool 257c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz JahanianGetNestedPaths(llvm::SmallVectorImpl<const CXXRecordDecl *> &NestedBasePaths, 258c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian const CXXRecordDecl *ClassDecl, 259c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian const CXXRecordDecl *BaseClassDecl) { 260c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(), 261c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian e = ClassDecl->bases_end(); i != e; ++i) { 262c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian if (i->isVirtual()) 263c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian continue; 264c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian const CXXRecordDecl *Base = 265104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 266c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian if (Base == BaseClassDecl) { 267c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian NestedBasePaths.push_back(BaseClassDecl); 268c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian return true; 269c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian } 270c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian } 271c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian // BaseClassDecl not an immediate base of ClassDecl. 272c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian for (CXXRecordDecl::base_class_const_iterator i = ClassDecl->bases_begin(), 273c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian e = ClassDecl->bases_end(); i != e; ++i) { 274c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian if (i->isVirtual()) 275c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian continue; 276c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian const CXXRecordDecl *Base = 277c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 278c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian if (GetNestedPaths(NestedBasePaths, Base, BaseClassDecl)) { 279c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian NestedBasePaths.push_back(Base); 280c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian return true; 281c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian } 282c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian } 283c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian return false; 284c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian} 285c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian 2869e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanianllvm::Value *CodeGenFunction::AddressCXXOfBaseClass(llvm::Value *BaseValue, 2876d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian const CXXRecordDecl *ClassDecl, 2886d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian const CXXRecordDecl *BaseClassDecl) { 2899e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian if (ClassDecl == BaseClassDecl) 2909e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian return BaseValue; 2919e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian 292c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian llvm::Type *I8Ptr = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); 293c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian llvm::SmallVector<const CXXRecordDecl *, 16> NestedBasePaths; 294c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian GetNestedPaths(NestedBasePaths, ClassDecl, BaseClassDecl); 295c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian assert(NestedBasePaths.size() > 0 && 296c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian "AddressCXXOfBaseClass - inheritence path failed"); 297c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian NestedBasePaths.push_back(ClassDecl); 298c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian uint64_t Offset = 0; 299c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian 3009e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian // Accessing a member of the base class. Must add delata to 3019e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian // the load of 'this'. 302c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian for (unsigned i = NestedBasePaths.size()-1; i > 0; i--) { 303c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian const CXXRecordDecl *DerivedClass = NestedBasePaths[i]; 304c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian const CXXRecordDecl *BaseClass = NestedBasePaths[i-1]; 305c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian const ASTRecordLayout &Layout = 306c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian getContext().getASTRecordLayout(DerivedClass); 307c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian Offset += Layout.getBaseClassOffset(BaseClass) / 8; 308c238a79a97ad35227a28acf16028ab63127c2fb7Fariborz Jahanian } 3095a8503b333f50acd6012859853612229f38cb420Fariborz Jahanian llvm::Value *OffsetVal = 3105a8503b333f50acd6012859853612229f38cb420Fariborz Jahanian llvm::ConstantInt::get( 3115a8503b333f50acd6012859853612229f38cb420Fariborz Jahanian CGM.getTypes().ConvertType(CGM.getContext().LongTy), Offset); 3129e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian BaseValue = Builder.CreateBitCast(BaseValue, I8Ptr); 3139e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian BaseValue = Builder.CreateGEP(BaseValue, OffsetVal, "add.ptr"); 3149e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian QualType BTy = 3159e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian getContext().getCanonicalType( 3166d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(BaseClassDecl))); 3179e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian const llvm::Type *BasePtr = ConvertType(BTy); 31896e0fc726c6fe7538522c60743705d5e696b40afOwen Anderson BasePtr = llvm::PointerType::getUnqual(BasePtr); 3199e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian BaseValue = Builder.CreateBitCast(BaseValue, BasePtr); 3209e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian return BaseValue; 3219e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian} 3229e809e7da2448c08aa11f15be4680226754678ceFariborz Jahanian 323b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlssonvoid 324b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders CarlssonCodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, 325b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson CXXCtorType Type, 326b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson llvm::Value *This, 327b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson CallExpr::const_arg_iterator ArgBeg, 328b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson CallExpr::const_arg_iterator ArgEnd) { 329b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); 330b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson 331b9de2c55b2a33776e2bee8ee57df7599b374c8a5Anders Carlsson EmitCXXMemberCall(D, Callee, This, ArgBeg, ArgEnd); 332b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson} 333b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson 3347267c1693abe7875b0c57268be05005ae013c6c9Anders Carlssonvoid CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *D, 3357267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson CXXDtorType Type, 3367267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson llvm::Value *This) { 3377267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(D, Type); 3387267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson 3397267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson EmitCXXMemberCall(D, Callee, This, 0, 0); 3407267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson} 3417267c1693abe7875b0c57268be05005ae013c6c9Anders Carlsson 342b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlssonvoid 34331ccf377f4a676eb6c205b47eef435de616d5e2dAnders CarlssonCodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, 34431ccf377f4a676eb6c205b47eef435de616d5e2dAnders Carlsson const CXXConstructExpr *E) { 345b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson assert(Dest && "Must have a destination!"); 346b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson 347b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson const CXXRecordDecl *RD = 3486217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); 349b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson if (RD->hasTrivialConstructor()) 350b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson return; 3516904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian 3526904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian // Code gen optimization to eliminate copy constructor and return 3536904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian // its first argument instead. 3541cf9ff87ee235ad252332a96699abdb32bd6facbFariborz Jahanian if (E->isElidable()) { 3556904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian CXXConstructExpr::const_arg_iterator i = E->arg_begin(); 3561cf9ff87ee235ad252332a96699abdb32bd6facbFariborz Jahanian EmitAggExpr((*i), Dest, false); 3571cf9ff87ee235ad252332a96699abdb32bd6facbFariborz Jahanian return; 3586904cbb1f21002317387e8fc7b14b7f8c09d198fFariborz Jahanian } 359b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson // Call the constructor. 360b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest, 361b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson E->arg_begin(), E->arg_end()); 362b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson} 363b14095aa98c6fedd3625920c4ce834bcaf24d9f7Anders Carlsson 364a00703dccbdc6cc4a293db38477dea7db5538c7eAnders Carlssonllvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { 365ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson if (E->isArray()) { 366ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson ErrorUnsupported(E, "new[] expression"); 36703e205031b08669f05c41eed5b896fc94c4a12bbOwen Anderson return llvm::UndefValue::get(ConvertType(E->getType())); 368ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 369ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 370ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType AllocType = E->getAllocatedType(); 371ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson FunctionDecl *NewFD = E->getOperatorNew(); 372ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson const FunctionProtoType *NewFTy = NewFD->getType()->getAsFunctionProtoType(); 373ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 374ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson CallArgList NewArgs; 375ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 376ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // The allocation size is the first argument. 377ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType SizeTy = getContext().getSizeType(); 378ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson llvm::Value *AllocSize = 3794a28d5deeba33722aa009eab488591fb9055cc7eOwen Anderson llvm::ConstantInt::get(ConvertType(SizeTy), 380ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson getContext().getTypeSize(AllocType) / 8); 381ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 382ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); 383ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 384ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // Emit the rest of the arguments. 385ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // FIXME: Ideally, this should just use EmitCallArgs. 386ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); 387ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 388ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // First, use the types from the function type. 389ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // We start at 1 here because the first argument (the allocation size) 390ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // has already been emitted. 391ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { 392ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType ArgType = NewFTy->getArgType(i); 393ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 394ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). 395ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson getTypePtr() == 396ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson getContext().getCanonicalType(NewArg->getType()).getTypePtr() && 397ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson "type mismatch in call argument!"); 398ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 399ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 400ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson ArgType)); 401ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 402ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 403ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 404ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // Either we've emitted all the call args, or we have a call to a 405ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // variadic function. 406ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && 407ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson "Extra arguments in non-variadic function!"); 408ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 409ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // If we still have any arguments, emit them using the type of the argument. 410ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); 411ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArg != NewArgEnd; ++NewArg) { 412ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson QualType ArgType = NewArg->getType(); 413ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 414ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson ArgType)); 415ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 416ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 417ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson // Emit the call to new. 418ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson RValue RV = 419ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), 420ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson CGM.GetAddrOfFunction(GlobalDecl(NewFD)), 421ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson NewArgs, NewFD); 422ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 423d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // If an allocation function is declared with an empty exception specification 424d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // it returns null to indicate failure to allocate storage. [expr.new]p13. 425d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // (We don't need to check for null when there's no new initializer and 426d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // we're allocating a POD type). 427d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && 428d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson !(AllocType->isPODType() && !E->hasInitializer()); 429ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson 430f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::BasicBlock *NewNull = 0; 431f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::BasicBlock *NewNotNull = 0; 432f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::BasicBlock *NewEnd = 0; 433f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 434f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::Value *NewPtr = RV.getScalarVal(); 435f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 436d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson if (NullCheckResult) { 437f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewNull = createBasicBlock("new.null"); 438f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewNotNull = createBasicBlock("new.notnull"); 439f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewEnd = createBasicBlock("new.end"); 440f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 441f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::Value *IsNull = 442f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson Builder.CreateICmpEQ(NewPtr, 443c9c88b4159791c48e486ca94e3743b5979e2b7a6Owen Anderson llvm::Constant::getNullValue(NewPtr->getType()), 444f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson "isnull"); 445f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 446f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson Builder.CreateCondBr(IsNull, NewNull, NewNotNull); 447f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson EmitBlock(NewNotNull); 448d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson } 449d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson 450f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); 451d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson 4526d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson if (AllocType->isPODType()) { 453215bd208d6eeff397bc4316d046ea8b4633efedfAnders Carlsson if (E->getNumConstructorArgs() > 0) { 4546d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson assert(E->getNumConstructorArgs() == 1 && 4556d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson "Can only have one argument to initializer of POD type."); 4566d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson 4576d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson const Expr *Init = E->getConstructorArg(0); 4586d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson 4593923e95280210ef877153f0c3dbab12d6ed2ad43Anders Carlsson if (!hasAggregateLLVMType(AllocType)) 4606d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson Builder.CreateStore(EmitScalarExpr(Init), NewPtr); 4613923e95280210ef877153f0c3dbab12d6ed2ad43Anders Carlsson else if (AllocType->isAnyComplexType()) 4623923e95280210ef877153f0c3dbab12d6ed2ad43Anders Carlsson EmitComplexExprIntoAddr(Init, NewPtr, AllocType.isVolatileQualified()); 463627a3e573f1d9f0429d62c7ceb742a21cdabfce0Anders Carlsson else 464627a3e573f1d9f0429d62c7ceb742a21cdabfce0Anders Carlsson EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); 4656d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson } 466d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson } else { 467d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson // Call the constructor. 468d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson CXXConstructorDecl *Ctor = E->getConstructor(); 4696d0ffad181215fc4ec0fca37c55eae82df6e0531Anders Carlsson 470d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, 471d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson E->constructor_arg_begin(), 472d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson E->constructor_arg_end()); 473ed4e367f8e27d2c700efdaff9412f2bf83ddba00Anders Carlsson } 474d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson 475f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson if (NullCheckResult) { 476f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson Builder.CreateBr(NewEnd); 477f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson EmitBlock(NewNull); 478f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson Builder.CreateBr(NewEnd); 479f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson EmitBlock(NewEnd); 480f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 481f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); 482f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson PHI->reserveOperandSpace(2); 483f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson PHI->addIncoming(NewPtr, NewNotNull); 484c9c88b4159791c48e486ca94e3743b5979e2b7a6Owen Anderson PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull); 485f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 486f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson NewPtr = PHI; 487f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson } 488f11085398dc27c0010663c711d4a10113e41d70fAnders Carlsson 489d3fd6bad1249d3f34d71b73e2333fab0db51cce4Anders Carlsson return NewPtr; 490a00703dccbdc6cc4a293db38477dea7db5538c7eAnders Carlsson} 491a00703dccbdc6cc4a293db38477dea7db5538c7eAnders Carlsson 49227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonstatic bool canGenerateCXXstructor(const CXXRecordDecl *RD, 49327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson ASTContext &Context) { 49459d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson // The class has base classes - we don't support that right now. 49559d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson if (RD->getNumBases() > 0) 49659d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson return false; 49759d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson 49817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); 49917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I != E; ++I) { 50059d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson // We don't support ctors for fields that aren't POD. 50159d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson if (!I->getType()->isPODType()) 50259d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson return false; 50359d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson } 50459d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson 50559d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson return true; 50659d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson} 50759d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson 50895d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlssonvoid CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { 50927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson if (!canGenerateCXXstructor(D->getParent(), getContext())) { 51059d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson ErrorUnsupported(D, "C++ constructor", true); 51159d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson return; 51259d8e0ff383274d992b3fa9ebee48b5e4a5ebdd1Anders Carlsson } 51395d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlsson 5142a131fbca2a51085dc083b8c56a2d4ced3cf1413Anders Carlsson EmitGlobal(GlobalDecl(D, Ctor_Complete)); 5152a131fbca2a51085dc083b8c56a2d4ced3cf1413Anders Carlsson EmitGlobal(GlobalDecl(D, Ctor_Base)); 51695d4e5d2f87a0f07fb143ccb824dfc4c5c595c78Anders Carlsson} 517363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson 51827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonvoid CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *D, 51927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXCtorType Type) { 52027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 52127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::Function *Fn = GetAddrOfCXXConstructor(D, Type); 52227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 52327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CodeGenFunction(*this).GenerateCode(D, Fn); 52427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 52527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetFunctionDefinitionAttributes(D, Fn); 52627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetLLVMFunctionAttributesForDefinition(D, Fn); 52727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 52827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 529363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlssonllvm::Function * 530363c184139e26ea38223b477ad64ee67b22bb9a7Anders CarlssonCodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, 531363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson CXXCtorType Type) { 532363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson const llvm::FunctionType *FTy = 533363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 534363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson 535363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson const char *Name = getMangledCXXCtorName(D, Type); 536b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner return cast<llvm::Function>( 537b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 538363c184139e26ea38223b477ad64ee67b22bb9a7Anders Carlsson} 53927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 54027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonconst char *CodeGenModule::getMangledCXXCtorName(const CXXConstructorDecl *D, 54127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXCtorType Type) { 54227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::SmallString<256> Name; 54327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::raw_svector_ostream Out(Name); 54427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson mangleCXXCtor(D, Type, Context, Out); 54527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 54627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson Name += '\0'; 54727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson return UniqueMangledName(Name.begin(), Name.end()); 54827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 54927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 55027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonvoid CodeGenModule::EmitCXXDestructors(const CXXDestructorDecl *D) { 55127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson if (!canGenerateCXXstructor(D->getParent(), getContext())) { 55227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson ErrorUnsupported(D, "C++ destructor", true); 55327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson return; 55427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson } 55527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 55627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson EmitCXXDestructor(D, Dtor_Complete); 55727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson EmitCXXDestructor(D, Dtor_Base); 55827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 55927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 56027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonvoid CodeGenModule::EmitCXXDestructor(const CXXDestructorDecl *D, 56127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 56227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::Function *Fn = GetAddrOfCXXDestructor(D, Type); 56327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 56427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CodeGenFunction(*this).GenerateCode(D, Fn); 56527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 56627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetFunctionDefinitionAttributes(D, Fn); 56727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson SetLLVMFunctionAttributesForDefinition(D, Fn); 56827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 56927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 57027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonllvm::Function * 57127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders CarlssonCodeGenModule::GetAddrOfCXXDestructor(const CXXDestructorDecl *D, 57227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 57327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson const llvm::FunctionType *FTy = 57427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson getTypes().GetFunctionType(getTypes().getFunctionInfo(D), false); 57527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 57627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson const char *Name = getMangledCXXDtorName(D, Type); 577b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner return cast<llvm::Function>( 578b4880bab7fc1b61267cfd9a0ad52188e7a828cb3Chris Lattner GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); 57927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 58027ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 58127ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlssonconst char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D, 58227ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson CXXDtorType Type) { 58327ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::SmallString<256> Name; 58427ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson llvm::raw_svector_ostream Out(Name); 58527ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson mangleCXXDtor(D, Type, Context, Out); 58627ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson 58727ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson Name += '\0'; 58827ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson return UniqueMangledName(Name.begin(), Name.end()); 58927ae53665f8b00fe4ba21da0fa79a4ce6e0b6cd5Anders Carlsson} 590e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian 591738f8c278da5950d0d4607de2debe0bdfad64185Mike Stumpllvm::Constant *CodeGenFunction::GenerateRtti(const CXXRecordDecl *RD) { 592738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::Type *Ptr8Ty; 593738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0); 594cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump llvm::Constant *Rtti = llvm::Constant::getNullValue(Ptr8Ty); 595738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 596738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump if (!getContext().getLangOptions().Rtti) 597cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump return Rtti; 598738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 599738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::SmallString<256> OutName; 600738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::raw_svector_ostream Out(OutName); 601738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump QualType ClassTy; 602e607ed068334bacb8d7b093996b4671c6ca79e25Mike Stump ClassTy = getContext().getTagDeclType(RD); 603738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump mangleCXXRtti(ClassTy, getContext(), Out); 604738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump const char *Name = OutName.c_str(); 605738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::GlobalVariable::LinkageTypes linktype; 606738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 607738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump std::vector<llvm::Constant *> info; 608e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump // assert (0 && "FIXME: implement rtti descriptor"); 609738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump // FIXME: descriptor 610738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); 611e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump // assert (0 && "FIXME: implement rtti ts"); 612738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump // FIXME: TS 613738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump info.push_back(llvm::Constant::getNullValue(Ptr8Ty)); 614738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 615738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::Constant *C; 616738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, info.size()); 617738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump C = llvm::ConstantArray::get(type, info); 618cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump Rtti = new llvm::GlobalVariable(CGM.getModule(), type, true, linktype, C, 619738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump Name); 620cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump Rtti = llvm::ConstantExpr::getBitCast(Rtti, Ptr8Ty); 621cb1b5d32fd227cd791fbd0614f75b32f291a5ccaMike Stump return Rtti; 622738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump} 623738f8c278da5950d0d4607de2debe0bdfad64185Mike Stump 6248a12b564923a72224730a467007e61b5701e4aa7Mike Stumpvoid CodeGenFunction::GenerateVtableForBase(const CXXRecordDecl *RD, 625e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump const CXXRecordDecl *Class, 626e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump llvm::Constant *rtti, 627e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump std::vector<llvm::Constant *> &methods, 62802cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump bool isPrimary, 62902cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump bool ForVirtualBase) { 6308a12b564923a72224730a467007e61b5701e4aa7Mike Stump typedef CXXRecordDecl::method_iterator meth_iter; 6318a12b564923a72224730a467007e61b5701e4aa7Mike Stump llvm::Type *Ptr8Ty; 6328a12b564923a72224730a467007e61b5701e4aa7Mike Stump Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0); 633e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump llvm::Constant *m = llvm::Constant::getNullValue(Ptr8Ty); 634e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump 635e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump if (RD && !RD->isDynamicClass()) 636e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump return; 63702cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump 63802cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump if (RD && ForVirtualBase) 63902cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; 64002cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump ++mi) { 64102cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump if (mi->isVirtual()) { 64202cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump // FIXME: vcall: offset for virtual base for this function 64302cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump m = llvm::Constant::getNullValue(Ptr8Ty); 64402cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump methods.push_back(m); 64502cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump } 64602cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump } 64702cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump if (isPrimary && ForVirtualBase) 64802cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump for (meth_iter mi = Class->method_begin(), 64902cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump me = Class->method_end(); mi != me; ++mi) { 65002cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump if (mi->isVirtual()) { 65102cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump // FIXME: vcall: offset for virtual base for this function 65202cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump m = llvm::Constant::getNullValue(Ptr8Ty); 65302cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump methods.push_back(m); 65402cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump } 65502cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump } 65602cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump 657e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump if (RD) { 658e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Class); 659e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump int64_t BaseOffset = -(Layout.getBaseClassOffset(RD) / 8); 660e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump m = llvm::ConstantInt::get(llvm::Type::Int64Ty, BaseOffset); 661e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); 662e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump } 663e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump methods.push_back(m); 664e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump methods.push_back(rtti); 665e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump 666e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump if (RD) 667e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me; 668e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump ++mi) { 669e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump if (mi->isVirtual()) { 670e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump m = CGM.GetAddrOfFunction(GlobalDecl(*mi)); 671e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump m = llvm::ConstantExpr::getBitCast(m, Ptr8Ty); 672e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump methods.push_back(m); 673e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump } 674e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump } 675e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump if (!isPrimary) 676e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump return; 677e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump 678e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump // And add the virtuals for the class to the primary vtable. 67902cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump for (meth_iter mi = Class->method_begin(), me = Class->method_end(); mi != me; 6808a12b564923a72224730a467007e61b5701e4aa7Mike Stump ++mi) { 6818a12b564923a72224730a467007e61b5701e4aa7Mike Stump if (mi->isVirtual()) { 6828a12b564923a72224730a467007e61b5701e4aa7Mike Stump m = CGM.GetAddrOfFunction(GlobalDecl(*mi)); 6838a12b564923a72224730a467007e61b5701e4aa7Mike Stump m = llvm::ConstantExpr::getBitCast(m, Ptr8Ty); 6848a12b564923a72224730a467007e61b5701e4aa7Mike Stump methods.push_back(m); 6858a12b564923a72224730a467007e61b5701e4aa7Mike Stump } 6868a12b564923a72224730a467007e61b5701e4aa7Mike Stump } 6878a12b564923a72224730a467007e61b5701e4aa7Mike Stump} 6888a12b564923a72224730a467007e61b5701e4aa7Mike Stump 689f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stumpllvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { 690f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::SmallString<256> OutName; 691f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::raw_svector_ostream Out(OutName); 692f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump QualType ClassTy; 693e607ed068334bacb8d7b093996b4671c6ca79e25Mike Stump ClassTy = getContext().getTagDeclType(RD); 694f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump mangleCXXVtable(ClassTy, getContext(), Out); 695f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump const char *Name = OutName.c_str(); 69682b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::GlobalVariable::LinkageTypes linktype; 69782b56961dcb813674dbda3c5f5aaee703d55741cMike Stump linktype = llvm::GlobalValue::WeakAnyLinkage; 69882b56961dcb813674dbda3c5f5aaee703d55741cMike Stump std::vector<llvm::Constant *> methods; 699f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump typedef CXXRecordDecl::method_iterator meth_iter; 70082b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::Type *Ptr8Ty; 70182b56961dcb813674dbda3c5f5aaee703d55741cMike Stump Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0); 7026f376336138ea719e3c4757ae046a5768043b276Mike Stump int64_t Offset = 0; 703e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump llvm::Constant *rtti = GenerateRtti(RD); 704e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump 705e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump Offset += LLVMPointerWidth; 706e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump Offset += LLVMPointerWidth; 7076f376336138ea719e3c4757ae046a5768043b276Mike Stump 7086f376336138ea719e3c4757ae046a5768043b276Mike Stump const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); 7096f376336138ea719e3c4757ae046a5768043b276Mike Stump const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); 710e6e1d609f6a14882be5336005f5d0222ef18b814Mike Stump const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual(); 711104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump 71257cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump // The virtual base offsets come first. 71357cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump for (CXXRecordDecl::reverse_base_class_const_iterator i = RD->vbases_rbegin(), 71457cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump e = RD->vbases_rend(); i != e; ++i) { 71557cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump const CXXRecordDecl *Base = 71657cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 71757cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump int64_t BaseOffset = Layout.getBaseClassOffset(Base) / 8; 71857cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump llvm::Constant *m; 71957cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump m = llvm::ConstantInt::get(llvm::Type::Int64Ty, BaseOffset); 72057cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty); 72157cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump methods.push_back(m); 72257cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump } 72357cf2f3abad1c3541cd388d9b7882d65cf6daa7cMike Stump 72470101ce87ff1d73ac90e4d99a3af0ae509e5934fMike Stump // The primary base comes first. 725928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump GenerateVtableForBase(PrimaryBase, RD, rtti, methods, true, 726928f1506eb38bb26a1284b876213a8f5244f6933Mike Stump PrimaryBaseWasVirtual); 727104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(), 728104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump e = RD->bases_end(); i != e; ++i) { 729104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump if (i->isVirtual()) 730104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump continue; 731104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump const CXXRecordDecl *Base = 732104ffaaa05d31d0a3dc886b7b18ebb2496bc2af4Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 7336f376336138ea719e3c4757ae046a5768043b276Mike Stump if (PrimaryBase != Base) { 734e1be2b16a3a24acda0b63c3dcb4ae3384fcdaf75Mike Stump GenerateVtableForBase(Base, RD, rtti, methods); 73582b56961dcb813674dbda3c5f5aaee703d55741cMike Stump } 736f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump } 73770101ce87ff1d73ac90e4d99a3af0ae509e5934fMike Stump 7388a12b564923a72224730a467007e61b5701e4aa7Mike Stump // FIXME: finish layout for virtual bases 7398a12b564923a72224730a467007e61b5701e4aa7Mike Stump // FIXME: audit indirect virtual bases 7408a12b564923a72224730a467007e61b5701e4aa7Mike Stump for (CXXRecordDecl::base_class_const_iterator i = RD->vbases_begin(), 7418a12b564923a72224730a467007e61b5701e4aa7Mike Stump e = RD->vbases_end(); i != e; ++i) { 7428a12b564923a72224730a467007e61b5701e4aa7Mike Stump const CXXRecordDecl *Base = 7438a12b564923a72224730a467007e61b5701e4aa7Mike Stump cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); 7448a12b564923a72224730a467007e61b5701e4aa7Mike Stump if (Base != PrimaryBase) 74502cf1e264719b4dada4377cc8a43888cb66f8815Mike Stump GenerateVtableForBase(Base, RD, rtti, methods, false, true); 7468a12b564923a72224730a467007e61b5701e4aa7Mike Stump } 7476f376336138ea719e3c4757ae046a5768043b276Mike Stump 74882b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::Constant *C; 74982b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::ArrayType *type = llvm::ArrayType::get(Ptr8Ty, methods.size()); 75082b56961dcb813674dbda3c5f5aaee703d55741cMike Stump C = llvm::ConstantArray::get(type, methods); 75182b56961dcb813674dbda3c5f5aaee703d55741cMike Stump llvm::Value *vtable = new llvm::GlobalVariable(CGM.getModule(), type, true, 75282b56961dcb813674dbda3c5f5aaee703d55741cMike Stump linktype, C, Name); 753f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump vtable = Builder.CreateBitCast(vtable, Ptr8Ty); 754f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump vtable = Builder.CreateGEP(vtable, 755f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::ConstantInt::get(llvm::Type::Int64Ty, 7566f376336138ea719e3c4757ae046a5768043b276Mike Stump Offset/8)); 757f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump return vtable; 758f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump} 759f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump 760ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian/// EmitClassMemberwiseCopy - This routine generates code to copy a class 761ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian/// object from SrcValue to DestValue. Copying can be either a bitwise copy 762ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian/// of via a copy constructor call. 763ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanianvoid CodeGenFunction::EmitClassMemberwiseCopy( 764942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian llvm::Value *Dest, llvm::Value *Src, 765ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian const CXXRecordDecl *ClassDecl, 766942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian const CXXRecordDecl *BaseClassDecl, QualType Ty) { 767942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian if (ClassDecl) { 768942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian Dest = AddressCXXOfBaseClass(Dest, ClassDecl, BaseClassDecl); 769942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian Src = AddressCXXOfBaseClass(Src, ClassDecl, BaseClassDecl) ; 770942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian } 771942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian if (BaseClassDecl->hasTrivialCopyConstructor()) { 772942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian EmitAggregateCopy(Dest, Src, Ty); 773ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian return; 774942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian } 775942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian 776ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian if (CXXConstructorDecl *BaseCopyCtor = 77780e4b9e0e87064a824d72b6ff89074206ecced58Fariborz Jahanian BaseClassDecl->getCopyConstructor(getContext(), 0)) { 778ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, 779ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian Ctor_Complete); 780ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgList CallArgs; 781ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian // Push the this (Dest) ptr. 782ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Dest), 783ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian BaseCopyCtor->getThisType(getContext()))); 784ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian 785ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian // Push the Src ptr. 786ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian CallArgs.push_back(std::make_pair(RValue::get(Src), 787ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian BaseCopyCtor->getThisType(getContext()))); 788ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian QualType ResultType = 789ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian BaseCopyCtor->getType()->getAsFunctionType()->getResultType(); 790ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian EmitCall(CGM.getTypes().getFunctionInfo(ResultType, CallArgs), 791ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian Callee, CallArgs, BaseCopyCtor); 792ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian } 793ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian} 794ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian 7958c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian/// SynthesizeCXXCopyConstructor - This routine implicitly defines body of a copy 79697a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// constructor, in accordance with section 12.8 (p7 and p8) of C++03 79797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// The implicitly-defined copy constructor for class X performs a memberwise 79897a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// copy of its subobjects. The order of copying is the same as the order 79997a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// of initialization of bases and members in a user-defined constructor 80097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// Each subobject is copied in the manner appropriate to its type: 80197a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// if the subobject is of class type, the copy constructor for the class is 80297a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// used; 80397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// if the subobject is an array, each element is copied, in the manner 80497a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// appropriate to the element type; 80597a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// if the subobject is of scalar type, the built-in assignment operator is 80697a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// used. 80797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// Virtual base class subobjects shall be copied only once by the 80897a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian/// implicitly-defined copy constructor 80997a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 8108c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanianvoid CodeGenFunction::SynthesizeCXXCopyConstructor(const CXXConstructorDecl *CD, 8118c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian const FunctionDecl *FD, 8128c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian llvm::Function *Fn, 813ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian const FunctionArgList &Args) { 81497a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); 81597a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian assert(!ClassDecl->hasUserDeclaredCopyConstructor() && 8168c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian "SynthesizeCXXCopyConstructor - copy constructor has definition already"); 8178c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian StartFunction(FD, FD->getResultType(), Fn, Args, SourceLocation()); 81897a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 8191e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian FunctionArgList::const_iterator i = Args.begin(); 8201e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian const VarDecl *ThisArg = i->first; 8211e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *ThisObj = GetAddrOfLocalVar(ThisArg); 8221e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *LoadOfThis = Builder.CreateLoad(ThisObj, "this"); 8231e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian const VarDecl *SrcArg = (i+1)->first; 8241e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *SrcObj = GetAddrOfLocalVar(SrcArg); 8251e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian llvm::Value *LoadOfSrc = Builder.CreateLoad(SrcObj); 8261e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian 82797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(); 82897a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian Base != ClassDecl->bases_end(); ++Base) { 82997a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian // FIXME. copy constrution of virtual base NYI 83097a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian if (Base->isVirtual()) 83197a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian continue; 832ca28361fb0a72c50e0a400fae2fad9520e61c0a5Fariborz Jahanian 83397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian CXXRecordDecl *BaseClassDecl 83497a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian = cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); 835942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian EmitClassMemberwiseCopy(LoadOfThis, LoadOfSrc, ClassDecl, BaseClassDecl, 836942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian Base->getType()); 83797a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian } 83897a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 8391e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 8401e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian FieldEnd = ClassDecl->field_end(); 8411e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian Field != FieldEnd; ++Field) { 8421e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian QualType FieldType = getContext().getCanonicalType((*Field)->getType()); 8431e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian 8441e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian // FIXME. How about copying arrays! 8451e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian assert(!getContext().getAsArrayType(FieldType) && 8461e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian "FIXME. Copying arrays NYI"); 8471e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian 8481e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian if (const RecordType *FieldClassType = FieldType->getAs<RecordType>()) { 8491e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian CXXRecordDecl *FieldClassDecl 8501e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian = cast<CXXRecordDecl>(FieldClassType->getDecl()); 8511e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, *Field, false, 0); 8521e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian LValue RHS = EmitLValueForField(LoadOfSrc, *Field, false, 0); 853942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian 8541e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian EmitClassMemberwiseCopy(LHS.getAddress(), RHS.getAddress(), 855942f4f33d02dba823594bd2d7b3d317cb01c74f8Fariborz Jahanian 0 /*ClassDecl*/, FieldClassDecl, FieldType); 8561e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian continue; 8571e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian } 8581e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian // FIXME. Do a built-in assignment of scalar data members. 8591e4edd5474f8cb966356afa6175d658002ff819cFariborz Jahanian } 8608c241a2844428eb1589c7b77fc6c1888295a2045Fariborz Jahanian FinishFunction(); 86197a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian} 86297a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 86397a937532c24a8ea44317d4fdee26d9701a1e83cFariborz Jahanian 864e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian/// EmitCtorPrologue - This routine generates necessary code to initialize 865e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian/// base classes and non-static data members belonging to this constructor. 866e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanianvoid CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) { 867742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext()); 868eb19fa948173502f47c26357c2ec41aa4be197b4Mike Stump // FIXME: Add vbase initialization 869f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *LoadOfThis = 0; 8706d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian 871742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), 872e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian E = CD->init_end(); 873e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian B != E; ++B) { 874e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian CXXBaseOrMemberInitializer *Member = (*B); 875e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian if (Member->isBaseInitializer()) { 876f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 8776d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian Type *BaseType = Member->getBaseClass(); 8786d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian CXXRecordDecl *BaseClassDecl = 8796217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); 8806d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian llvm::Value *V = AddressCXXOfBaseClass(LoadOfThis, ClassDecl, 8816d0bdaa68989bee60c85274e82a8f9c982587f26Fariborz Jahanian BaseClassDecl); 882742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian EmitCXXConstructorCall(Member->getConstructor(), 883742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian Ctor_Complete, V, 884742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian Member->const_arg_begin(), 885742cd1b7bb86b52b23b335d47abbd842dac0e1bfFariborz Jahanian Member->const_arg_end()); 886b3589f44c5d295cd41de2c83f3475116835eeebdMike Stump } else { 887e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian // non-static data member initilaizers. 888e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian FieldDecl *Field = Member->getMember(); 889e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian QualType FieldType = getContext().getCanonicalType((Field)->getType()); 890e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian assert(!getContext().getAsArrayType(FieldType) 891e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian && "FIXME. Field arrays initialization unsupported"); 89250b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian 893f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 894e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0); 8956217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (FieldType->getAs<RecordType>()) { 89650b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian 89750b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian assert(Member->getConstructor() && 89850b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian "EmitCtorPrologue - no constructor to initialize member"); 89950b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian EmitCXXConstructorCall(Member->getConstructor(), 90050b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian Ctor_Complete, LHS.getAddress(), 90150b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian Member->const_arg_begin(), 90250b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian Member->const_arg_end()); 90350b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian continue; 90450b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian } 905e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian 906e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian assert(Member->getNumArgs() == 1 && "Initializer count must be 1 only"); 90750b8eea3f36881a988a5757e0f6e15d45900324bFariborz Jahanian Expr *RhsExpr = *Member->arg_begin(); 908e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian llvm::Value *RHS = EmitScalarExpr(RhsExpr, true); 909e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian if (LHS.isBitfield()) 910e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian EmitStoreThroughBitfieldLValue(RValue::get(RHS), LHS, FieldType, 0); 911e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian else 912e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian EmitStoreThroughLValue(RValue::get(RHS), LHS, FieldType); 913e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian } 914e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian } 915f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump 916f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump // Initialize the vtable pointer 917b502d839994cc3828573bd9ea472418e3536f415Mike Stump if (ClassDecl->isDynamicClass()) { 918f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump if (!LoadOfThis) 919f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump LoadOfThis = LoadCXXThis(); 920f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *VtableField; 921f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Type *Ptr8Ty, *PtrPtr8Ty; 922f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0); 923f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0); 924f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump VtableField = Builder.CreateBitCast(LoadOfThis, PtrPtr8Ty); 925f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump llvm::Value *vtable = GenerateVtable(ClassDecl); 926f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump Builder.CreateStore(vtable, VtableField); 927f121677b6bbbf4e4a51ee7a1120b77adf187bad4Mike Stump } 928e7d346b6d5cee14b75e34928b3fd423f21d8d80dFariborz Jahanian} 929426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian 930426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian/// EmitDtorEpilogue - Emit all code that comes at the end of class's 931426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian/// destructor. This is to call destructors on members and base classes 932426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian/// in reverse order of their construction. 933426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanianvoid CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD) { 934426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(DD->getDeclContext()); 935426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian assert(!ClassDecl->isPolymorphic() && 936426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian "FIXME. polymorphic destruction not supported"); 937426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian (void)ClassDecl; // prevent warning. 938426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian 939426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian for (CXXDestructorDecl::destr_const_iterator *B = DD->destr_begin(), 940426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian *E = DD->destr_end(); B != E; ++B) { 941426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian uintptr_t BaseOrMember = (*B); 942426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (DD->isMemberToDestroy(BaseOrMember)) { 943426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian FieldDecl *FD = DD->getMemberToDestroy(BaseOrMember); 944426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian QualType FieldType = getContext().getCanonicalType((FD)->getType()); 945426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian assert(!getContext().getAsArrayType(FieldType) 946426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian && "FIXME. Field arrays destruction unsupported"); 947426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const RecordType *RT = FieldType->getAs<RecordType>(); 948426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 949426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (FieldClassDecl->hasTrivialDestructor()) 950426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian continue; 951426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian llvm::Value *LoadOfThis = LoadCXXThis(); 952426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian LValue LHS = EmitLValueForField(LoadOfThis, FD, false, 0); 953426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), 954426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian Dtor_Complete, LHS.getAddress()); 955b3589f44c5d295cd41de2c83f3475116835eeebdMike Stump } else { 956426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian const RecordType *RT = 957426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian DD->getAnyBaseClassToDestroy(BaseOrMember)->getAs<RecordType>(); 958426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(RT->getDecl()); 959426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian if (BaseClassDecl->hasTrivialDestructor()) 960426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian continue; 961426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian llvm::Value *V = AddressCXXOfBaseClass(LoadCXXThis(), 962426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian ClassDecl,BaseClassDecl); 963426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian EmitCXXDestructorCall(BaseClassDecl->getDestructor(getContext()), 964426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian Dtor_Complete, V); 965426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian } 966426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian } 967426cc3828ce07a2cff15c9837f5958e6fc4b7739Fariborz Jahanian} 968