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