diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp | 1325 |
1 files changed, 1325 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp new file mode 100644 index 0000000..bebea54 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGClass.cpp @@ -0,0 +1,1325 @@ +//===--- CGClass.cpp - Emit LLVM Code for C++ classes ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This contains code dealing with C++ code generation of classes +// +//===----------------------------------------------------------------------===// + +#include "CodeGenFunction.h" +#include "clang/AST/CXXInheritance.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/StmtCXX.h" + +using namespace clang; +using namespace CodeGen; + +static uint64_t +ComputeNonVirtualBaseClassOffset(ASTContext &Context, + const CXXRecordDecl *DerivedClass, + CXXBaseSpecifierArray::iterator Start, + CXXBaseSpecifierArray::iterator End) { + uint64_t Offset = 0; + + const CXXRecordDecl *RD = DerivedClass; + + for (CXXBaseSpecifierArray::iterator I = Start; I != End; ++I) { + const CXXBaseSpecifier *Base = *I; + assert(!Base->isVirtual() && "Should not see virtual bases here!"); + + // Get the layout. + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); + + const CXXRecordDecl *BaseDecl = + cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + + // Add the offset. + Offset += Layout.getBaseClassOffset(BaseDecl); + + RD = BaseDecl; + } + + // FIXME: We should not use / 8 here. + return Offset / 8; +} + +llvm::Constant * +CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl, + const CXXBaseSpecifierArray &BasePath) { + assert(!BasePath.empty() && "Base path should not be empty!"); + + uint64_t Offset = + ComputeNonVirtualBaseClassOffset(getContext(), ClassDecl, + BasePath.begin(), BasePath.end()); + if (!Offset) + return 0; + + const llvm::Type *PtrDiffTy = + Types.ConvertType(getContext().getPointerDiffType()); + + return llvm::ConstantInt::get(PtrDiffTy, Offset); +} + +/// Gets the address of a direct base class within a complete object. +/// This should only be used for (1) non-virtual bases or (2) virtual bases +/// when the type is known to be complete (e.g. in complete destructors). +/// +/// The object pointed to by 'This' is assumed to be non-null. +llvm::Value * +CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(llvm::Value *This, + const CXXRecordDecl *Derived, + const CXXRecordDecl *Base, + bool BaseIsVirtual) { + // 'this' must be a pointer (in some address space) to Derived. + assert(This->getType()->isPointerTy() && + cast<llvm::PointerType>(This->getType())->getElementType() + == ConvertType(Derived)); + + // Compute the offset of the virtual base. + uint64_t Offset; + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived); + if (BaseIsVirtual) + Offset = Layout.getVBaseClassOffset(Base); + else + Offset = Layout.getBaseClassOffset(Base); + + // Shift and cast down to the base type. + // TODO: for complete types, this should be possible with a GEP. + llvm::Value *V = This; + if (Offset) { + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); + V = Builder.CreateBitCast(V, Int8PtrTy); + V = Builder.CreateConstInBoundsGEP1_64(V, Offset / 8); + } + V = Builder.CreateBitCast(V, ConvertType(Base)->getPointerTo()); + + return V; +} + +static llvm::Value * +ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, llvm::Value *ThisPtr, + uint64_t NonVirtual, llvm::Value *Virtual) { + const llvm::Type *PtrDiffTy = + CGF.ConvertType(CGF.getContext().getPointerDiffType()); + + llvm::Value *NonVirtualOffset = 0; + if (NonVirtual) + NonVirtualOffset = llvm::ConstantInt::get(PtrDiffTy, NonVirtual); + + llvm::Value *BaseOffset; + if (Virtual) { + if (NonVirtualOffset) + BaseOffset = CGF.Builder.CreateAdd(Virtual, NonVirtualOffset); + else + BaseOffset = Virtual; + } else + BaseOffset = NonVirtualOffset; + + // Apply the base offset. + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); + ThisPtr = CGF.Builder.CreateBitCast(ThisPtr, Int8PtrTy); + ThisPtr = CGF.Builder.CreateGEP(ThisPtr, BaseOffset, "add.ptr"); + + return ThisPtr; +} + +llvm::Value * +CodeGenFunction::GetAddressOfBaseClass(llvm::Value *Value, + const CXXRecordDecl *Derived, + const CXXBaseSpecifierArray &BasePath, + bool NullCheckValue) { + assert(!BasePath.empty() && "Base path should not be empty!"); + + CXXBaseSpecifierArray::iterator Start = BasePath.begin(); + const CXXRecordDecl *VBase = 0; + + // Get the virtual base. + if ((*Start)->isVirtual()) { + VBase = + cast<CXXRecordDecl>((*Start)->getType()->getAs<RecordType>()->getDecl()); + ++Start; + } + + uint64_t NonVirtualOffset = + ComputeNonVirtualBaseClassOffset(getContext(), VBase ? VBase : Derived, + Start, BasePath.end()); + + // Get the base pointer type. + const llvm::Type *BasePtrTy = + ConvertType((BasePath.end()[-1])->getType())->getPointerTo(); + + if (!NonVirtualOffset && !VBase) { + // Just cast back. + return Builder.CreateBitCast(Value, BasePtrTy); + } + + llvm::BasicBlock *CastNull = 0; + llvm::BasicBlock *CastNotNull = 0; + llvm::BasicBlock *CastEnd = 0; + + if (NullCheckValue) { + CastNull = createBasicBlock("cast.null"); + CastNotNull = createBasicBlock("cast.notnull"); + CastEnd = createBasicBlock("cast.end"); + + llvm::Value *IsNull = + Builder.CreateICmpEQ(Value, + llvm::Constant::getNullValue(Value->getType())); + Builder.CreateCondBr(IsNull, CastNull, CastNotNull); + EmitBlock(CastNotNull); + } + + llvm::Value *VirtualOffset = 0; + + if (VBase) + VirtualOffset = GetVirtualBaseClassOffset(Value, Derived, VBase); + + // Apply the offsets. + Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset, + VirtualOffset); + + // Cast back. + Value = Builder.CreateBitCast(Value, BasePtrTy); + + if (NullCheckValue) { + Builder.CreateBr(CastEnd); + EmitBlock(CastNull); + Builder.CreateBr(CastEnd); + EmitBlock(CastEnd); + + llvm::PHINode *PHI = Builder.CreatePHI(Value->getType()); + PHI->reserveOperandSpace(2); + PHI->addIncoming(Value, CastNotNull); + PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), + CastNull); + Value = PHI; + } + + return Value; +} + +llvm::Value * +CodeGenFunction::GetAddressOfDerivedClass(llvm::Value *Value, + const CXXRecordDecl *Derived, + const CXXBaseSpecifierArray &BasePath, + bool NullCheckValue) { + assert(!BasePath.empty() && "Base path should not be empty!"); + + QualType DerivedTy = + getContext().getCanonicalType(getContext().getTagDeclType(Derived)); + const llvm::Type *DerivedPtrTy = ConvertType(DerivedTy)->getPointerTo(); + + llvm::Value *NonVirtualOffset = + CGM.GetNonVirtualBaseClassOffset(Derived, BasePath); + + if (!NonVirtualOffset) { + // No offset, we can just cast back. + return Builder.CreateBitCast(Value, DerivedPtrTy); + } + + llvm::BasicBlock *CastNull = 0; + llvm::BasicBlock *CastNotNull = 0; + llvm::BasicBlock *CastEnd = 0; + + if (NullCheckValue) { + CastNull = createBasicBlock("cast.null"); + CastNotNull = createBasicBlock("cast.notnull"); + CastEnd = createBasicBlock("cast.end"); + + llvm::Value *IsNull = + Builder.CreateICmpEQ(Value, + llvm::Constant::getNullValue(Value->getType())); + Builder.CreateCondBr(IsNull, CastNull, CastNotNull); + EmitBlock(CastNotNull); + } + + // Apply the offset. + Value = Builder.CreatePtrToInt(Value, NonVirtualOffset->getType()); + Value = Builder.CreateSub(Value, NonVirtualOffset); + Value = Builder.CreateIntToPtr(Value, DerivedPtrTy); + + // Just cast. + Value = Builder.CreateBitCast(Value, DerivedPtrTy); + + if (NullCheckValue) { + Builder.CreateBr(CastEnd); + EmitBlock(CastNull); + Builder.CreateBr(CastEnd); + EmitBlock(CastEnd); + + llvm::PHINode *PHI = Builder.CreatePHI(Value->getType()); + PHI->reserveOperandSpace(2); + PHI->addIncoming(Value, CastNotNull); + PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), + CastNull); + Value = PHI; + } + + return Value; +} + +/// GetVTTParameter - Return the VTT parameter that should be passed to a +/// base constructor/destructor with virtual bases. +static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, + bool ForVirtualBase) { + if (!CodeGenVTables::needsVTTParameter(GD)) { + // This constructor/destructor does not need a VTT parameter. + return 0; + } + + const CXXRecordDecl *RD = cast<CXXMethodDecl>(CGF.CurFuncDecl)->getParent(); + const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent(); + + llvm::Value *VTT; + + uint64_t SubVTTIndex; + + // If the record matches the base, this is the complete ctor/dtor + // variant calling the base variant in a class with virtual bases. + if (RD == Base) { + assert(!CodeGenVTables::needsVTTParameter(CGF.CurGD) && + "doing no-op VTT offset in base dtor/ctor?"); + assert(!ForVirtualBase && "Can't have same class as virtual base!"); + SubVTTIndex = 0; + } else { + const ASTRecordLayout &Layout = + CGF.getContext().getASTRecordLayout(RD); + uint64_t BaseOffset = ForVirtualBase ? + Layout.getVBaseClassOffset(Base) : Layout.getBaseClassOffset(Base); + + SubVTTIndex = + CGF.CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset)); + assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!"); + } + + if (CodeGenVTables::needsVTTParameter(CGF.CurGD)) { + // A VTT parameter was passed to the constructor, use it. + VTT = CGF.LoadCXXVTT(); + VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex); + } else { + // We're the complete constructor, so get the VTT by name. + VTT = CGF.CGM.getVTables().getVTT(RD); + VTT = CGF.Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex); + } + + return VTT; +} + +static void EmitBaseInitializer(CodeGenFunction &CGF, + const CXXRecordDecl *ClassDecl, + CXXBaseOrMemberInitializer *BaseInit, + CXXCtorType CtorType) { + assert(BaseInit->isBaseInitializer() && + "Must have base initializer!"); + + llvm::Value *ThisPtr = CGF.LoadCXXThis(); + + const Type *BaseType = BaseInit->getBaseClass(); + CXXRecordDecl *BaseClassDecl = + cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl()); + + bool isBaseVirtual = BaseInit->isBaseVirtual(); + + // The base constructor doesn't construct virtual bases. + if (CtorType == Ctor_Base && isBaseVirtual) + return; + + // We can pretend to be a complete class because it only matters for + // virtual bases, and we only do virtual bases for complete ctors. + llvm::Value *V = + CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl, + BaseClassDecl, + BaseInit->isBaseVirtual()); + + CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true); + + if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) { + // FIXME: Is this OK for C++0x delegating constructors? + CodeGenFunction::EHCleanupBlock Cleanup(CGF); + + CXXDestructorDecl *DD = BaseClassDecl->getDestructor(CGF.getContext()); + CGF.EmitCXXDestructorCall(DD, Dtor_Base, isBaseVirtual, V); + } +} + +static void EmitAggMemberInitializer(CodeGenFunction &CGF, + LValue LHS, + llvm::Value *ArrayIndexVar, + CXXBaseOrMemberInitializer *MemberInit, + QualType T, + unsigned Index) { + if (Index == MemberInit->getNumArrayIndices()) { + CodeGenFunction::CleanupScope Cleanups(CGF); + + llvm::Value *Dest = LHS.getAddress(); + if (ArrayIndexVar) { + // If we have an array index variable, load it and use it as an offset. + // Then, increment the value. + llvm::Value *ArrayIndex = CGF.Builder.CreateLoad(ArrayIndexVar); + Dest = CGF.Builder.CreateInBoundsGEP(Dest, ArrayIndex, "destaddress"); + llvm::Value *Next = llvm::ConstantInt::get(ArrayIndex->getType(), 1); + Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc"); + CGF.Builder.CreateStore(Next, ArrayIndexVar); + } + + CGF.EmitAggExpr(MemberInit->getInit(), Dest, + LHS.isVolatileQualified(), + /*IgnoreResult*/ false, + /*IsInitializer*/ true); + + return; + } + + const ConstantArrayType *Array = CGF.getContext().getAsConstantArrayType(T); + assert(Array && "Array initialization without the array type?"); + llvm::Value *IndexVar + = CGF.GetAddrOfLocalVar(MemberInit->getArrayIndex(Index)); + assert(IndexVar && "Array index variable not loaded"); + + // Initialize this index variable to zero. + llvm::Value* Zero + = llvm::Constant::getNullValue( + CGF.ConvertType(CGF.getContext().getSizeType())); + CGF.Builder.CreateStore(Zero, IndexVar); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = CGF.createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = CGF.createBasicBlock("for.end"); + + CGF.EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = CGF.createBasicBlock("for.body"); + // Generate: if (loop-index < number-of-elements) fall to the loop body, + // otherwise, go to the block after the for-loop. + uint64_t NumElements = Array->getSize().getZExtValue(); + llvm::Value *Counter = CGF.Builder.CreateLoad(IndexVar); + llvm::Value *NumElementsPtr = + llvm::ConstantInt::get(Counter->getType(), NumElements); + llvm::Value *IsLess = CGF.Builder.CreateICmpULT(Counter, NumElementsPtr, + "isless"); + + // If the condition is true, execute the body. + CGF.Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + CGF.EmitBlock(ForBody); + llvm::BasicBlock *ContinueBlock = CGF.createBasicBlock("for.inc"); + + { + CodeGenFunction::CleanupScope Cleanups(CGF); + + // Inside the loop body recurse to emit the inner loop or, eventually, the + // constructor call. + EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, + Array->getElementType(), Index + 1); + } + + CGF.EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(Counter->getType(), 1); + Counter = CGF.Builder.CreateLoad(IndexVar); + NextVal = CGF.Builder.CreateAdd(Counter, NextVal, "inc"); + CGF.Builder.CreateStore(NextVal, IndexVar); + + // Finally, branch back up to the condition for the next iteration. + CGF.EmitBranch(CondBlock); + + // Emit the fall-through block. + CGF.EmitBlock(AfterFor, true); +} + +static void EmitMemberInitializer(CodeGenFunction &CGF, + const CXXRecordDecl *ClassDecl, + CXXBaseOrMemberInitializer *MemberInit, + const CXXConstructorDecl *Constructor, + FunctionArgList &Args) { + assert(MemberInit->isMemberInitializer() && + "Must have member initializer!"); + + // non-static data member initializers. + FieldDecl *Field = MemberInit->getMember(); + QualType FieldType = CGF.getContext().getCanonicalType(Field->getType()); + + llvm::Value *ThisPtr = CGF.LoadCXXThis(); + LValue LHS; + + // If we are initializing an anonymous union field, drill down to the field. + if (MemberInit->getAnonUnionMember()) { + Field = MemberInit->getAnonUnionMember(); + LHS = CGF.EmitLValueForAnonRecordField(ThisPtr, Field, 0); + FieldType = Field->getType(); + } else { + LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0); + } + + // FIXME: If there's no initializer and the CXXBaseOrMemberInitializer + // was implicitly generated, we shouldn't be zeroing memory. + RValue RHS; + if (FieldType->isReferenceType()) { + RHS = CGF.EmitReferenceBindingToExpr(MemberInit->getInit(), + /*IsInitializer=*/true); + CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); + } else if (FieldType->isArrayType() && !MemberInit->getInit()) { + CGF.EmitNullInitialization(LHS.getAddress(), Field->getType()); + } else if (!CGF.hasAggregateLLVMType(Field->getType())) { + RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit(), true)); + CGF.EmitStoreThroughLValue(RHS, LHS, FieldType); + } else if (MemberInit->getInit()->getType()->isAnyComplexType()) { + CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(), + LHS.isVolatileQualified()); + } else { + llvm::Value *ArrayIndexVar = 0; + const ConstantArrayType *Array + = CGF.getContext().getAsConstantArrayType(FieldType); + if (Array && Constructor->isImplicit() && + Constructor->isCopyConstructor()) { + const llvm::Type *SizeTy + = CGF.ConvertType(CGF.getContext().getSizeType()); + + // The LHS is a pointer to the first object we'll be constructing, as + // a flat array. + QualType BaseElementTy = CGF.getContext().getBaseElementType(Array); + const llvm::Type *BasePtr = CGF.ConvertType(BaseElementTy); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = CGF.Builder.CreateBitCast(LHS.getAddress(), + BasePtr); + LHS = LValue::MakeAddr(BaseAddrPtr, CGF.MakeQualifiers(BaseElementTy)); + + // Create an array index that will be used to walk over all of the + // objects we're constructing. + ArrayIndexVar = CGF.CreateTempAlloca(SizeTy, "object.index"); + llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy); + CGF.Builder.CreateStore(Zero, ArrayIndexVar); + + // If we are copying an array of scalars or classes with trivial copy + // constructors, perform a single aggregate copy. + const RecordType *Record = BaseElementTy->getAs<RecordType>(); + if (!Record || + cast<CXXRecordDecl>(Record->getDecl())->hasTrivialCopyConstructor()) { + // Find the source pointer. We knows it's the last argument because + // we know we're in a copy constructor. + unsigned SrcArgIndex = Args.size() - 1; + llvm::Value *SrcPtr + = CGF.Builder.CreateLoad( + CGF.GetAddrOfLocalVar(Args[SrcArgIndex].first)); + LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0); + + // Copy the aggregate. + CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType, + LHS.isVolatileQualified()); + return; + } + + // Emit the block variables for the array indices, if any. + for (unsigned I = 0, N = MemberInit->getNumArrayIndices(); I != N; ++I) + CGF.EmitLocalBlockVarDecl(*MemberInit->getArrayIndex(I)); + } + + EmitAggMemberInitializer(CGF, LHS, ArrayIndexVar, MemberInit, FieldType, 0); + + if (!CGF.Exceptions) + return; + + // FIXME: If we have an array of classes w/ non-trivial destructors, + // we need to destroy in reverse order of construction along the exception + // path. + const RecordType *RT = FieldType->getAs<RecordType>(); + if (!RT) + return; + + CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + if (!RD->hasTrivialDestructor()) { + // FIXME: Is this OK for C++0x delegating constructors? + CodeGenFunction::EHCleanupBlock Cleanup(CGF); + + llvm::Value *ThisPtr = CGF.LoadCXXThis(); + LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0); + + CXXDestructorDecl *DD = RD->getDestructor(CGF.getContext()); + CGF.EmitCXXDestructorCall(DD, Dtor_Complete, /*ForVirtualBase=*/false, + LHS.getAddress()); + } + } +} + +/// Checks whether the given constructor is a valid subject for the +/// complete-to-base constructor delegation optimization, i.e. +/// emitting the complete constructor as a simple call to the base +/// constructor. +static bool IsConstructorDelegationValid(const CXXConstructorDecl *Ctor) { + + // Currently we disable the optimization for classes with virtual + // bases because (1) the addresses of parameter variables need to be + // consistent across all initializers but (2) the delegate function + // call necessarily creates a second copy of the parameter variable. + // + // The limiting example (purely theoretical AFAIK): + // struct A { A(int &c) { c++; } }; + // struct B : virtual A { + // B(int count) : A(count) { printf("%d\n", count); } + // }; + // ...although even this example could in principle be emitted as a + // delegation since the address of the parameter doesn't escape. + if (Ctor->getParent()->getNumVBases()) { + // TODO: white-list trivial vbase initializers. This case wouldn't + // be subject to the restrictions below. + + // TODO: white-list cases where: + // - there are no non-reference parameters to the constructor + // - the initializers don't access any non-reference parameters + // - the initializers don't take the address of non-reference + // parameters + // - etc. + // If we ever add any of the above cases, remember that: + // - function-try-blocks will always blacklist this optimization + // - we need to perform the constructor prologue and cleanup in + // EmitConstructorBody. + + return false; + } + + // We also disable the optimization for variadic functions because + // it's impossible to "re-pass" varargs. + if (Ctor->getType()->getAs<FunctionProtoType>()->isVariadic()) + return false; + + return true; +} + +/// EmitConstructorBody - Emits the body of the current constructor. +void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) { + const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl()); + CXXCtorType CtorType = CurGD.getCtorType(); + + // Before we go any further, try the complete->base constructor + // delegation optimization. + if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor)) { + EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args); + return; + } + + Stmt *Body = Ctor->getBody(); + + // Enter the function-try-block before the constructor prologue if + // applicable. + CXXTryStmtInfo TryInfo; + bool IsTryBody = (Body && isa<CXXTryStmt>(Body)); + + if (IsTryBody) + TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body)); + + unsigned CleanupStackSize = CleanupEntries.size(); + + // Emit the constructor prologue, i.e. the base and member + // initializers. + EmitCtorPrologue(Ctor, CtorType, Args); + + // Emit the body of the statement. + if (IsTryBody) + EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); + else if (Body) + EmitStmt(Body); + + // Emit any cleanup blocks associated with the member or base + // initializers, which includes (along the exceptional path) the + // destructors for those members and bases that were fully + // constructed. + EmitCleanupBlocks(CleanupStackSize); + + if (IsTryBody) + ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo); +} + +/// EmitCtorPrologue - This routine generates necessary code to initialize +/// base classes and non-static data members belonging to this constructor. +void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD, + CXXCtorType CtorType, + FunctionArgList &Args) { + const CXXRecordDecl *ClassDecl = CD->getParent(); + + llvm::SmallVector<CXXBaseOrMemberInitializer *, 8> MemberInitializers; + + for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(), + E = CD->init_end(); + B != E; ++B) { + CXXBaseOrMemberInitializer *Member = (*B); + + assert(LiveTemporaries.empty() && + "Should not have any live temporaries at initializer start!"); + + if (Member->isBaseInitializer()) + EmitBaseInitializer(*this, ClassDecl, Member, CtorType); + else + MemberInitializers.push_back(Member); + } + + InitializeVTablePointers(ClassDecl); + + for (unsigned I = 0, E = MemberInitializers.size(); I != E; ++I) { + assert(LiveTemporaries.empty() && + "Should not have any live temporaries at initializer start!"); + + EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I], CD, Args); + } +} + +/// EmitDestructorBody - Emits the body of the current destructor. +void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { + const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl()); + CXXDtorType DtorType = CurGD.getDtorType(); + + Stmt *Body = Dtor->getBody(); + + // If the body is a function-try-block, enter the try before + // anything else --- unless we're in a deleting destructor, in which + // case we're just going to call the complete destructor and then + // call operator delete() on the way out. + CXXTryStmtInfo TryInfo; + bool isTryBody = (DtorType != Dtor_Deleting && + Body && isa<CXXTryStmt>(Body)); + if (isTryBody) + TryInfo = EnterCXXTryStmt(*cast<CXXTryStmt>(Body)); + + llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue"); + PushCleanupBlock(DtorEpilogue); + + bool SkipBody = false; // should get jump-threaded + + // If this is the deleting variant, just invoke the complete + // variant, then call the appropriate operator delete() on the way + // out. + if (DtorType == Dtor_Deleting) { + EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, + LoadCXXThis()); + SkipBody = true; + + // If this is the complete variant, just invoke the base variant; + // the epilogue will destruct the virtual bases. But we can't do + // this optimization if the body is a function-try-block, because + // we'd introduce *two* handler blocks. + } else if (!isTryBody && DtorType == Dtor_Complete) { + EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, + LoadCXXThis()); + SkipBody = true; + + // Otherwise, we're in the base variant, so we need to ensure the + // vtable ptrs are right before emitting the body. + } else { + InitializeVTablePointers(Dtor->getParent()); + } + + // Emit the body of the statement. + if (SkipBody) + (void) 0; + else if (isTryBody) + EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock()); + else if (Body) + EmitStmt(Body); + else { + assert(Dtor->isImplicit() && "bodyless dtor not implicit"); + // nothing to do besides what's in the epilogue + } + + // Jump to the cleanup block. + CleanupBlockInfo Info = PopCleanupBlock(); + assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!"); + EmitBlock(DtorEpilogue); + + // Emit the destructor epilogue now. If this is a complete + // destructor with a function-try-block, perform the base epilogue + // as well. + if (isTryBody && DtorType == Dtor_Complete) + EmitDtorEpilogue(Dtor, Dtor_Base); + EmitDtorEpilogue(Dtor, DtorType); + + // Link up the cleanup information. + if (Info.SwitchBlock) + EmitBlock(Info.SwitchBlock); + if (Info.EndBlock) + EmitBlock(Info.EndBlock); + + // Exit the try if applicable. + if (isTryBody) + ExitCXXTryStmt(*cast<CXXTryStmt>(Body), TryInfo); +} + +/// EmitDtorEpilogue - Emit all code that comes at the end of class's +/// destructor. This is to call destructors on members and base classes +/// in reverse order of their construction. +void CodeGenFunction::EmitDtorEpilogue(const CXXDestructorDecl *DD, + CXXDtorType DtorType) { + assert(!DD->isTrivial() && + "Should not emit dtor epilogue for trivial dtor!"); + + const CXXRecordDecl *ClassDecl = DD->getParent(); + + // In a deleting destructor, we've already called the complete + // destructor as a subroutine, so we just have to delete the + // appropriate value. + if (DtorType == Dtor_Deleting) { + assert(DD->getOperatorDelete() && + "operator delete missing - EmitDtorEpilogue"); + EmitDeleteCall(DD->getOperatorDelete(), LoadCXXThis(), + getContext().getTagDeclType(ClassDecl)); + return; + } + + // For complete destructors, we've already called the base + // destructor (in GenerateBody), so we just need to destruct all the + // virtual bases. + if (DtorType == Dtor_Complete) { + // Handle virtual bases. + for (CXXRecordDecl::reverse_base_class_const_iterator I = + ClassDecl->vbases_rbegin(), E = ClassDecl->vbases_rend(); + I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); + + // Ignore trivial destructors. + if (BaseClassDecl->hasTrivialDestructor()) + continue; + const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext()); + llvm::Value *V = + GetAddressOfDirectBaseInCompleteClass(LoadCXXThis(), + ClassDecl, BaseClassDecl, + /*BaseIsVirtual=*/true); + EmitCXXDestructorCall(D, Dtor_Base, /*ForVirtualBase=*/true, V); + } + return; + } + + assert(DtorType == Dtor_Base); + + // Collect the fields. + llvm::SmallVector<const FieldDecl *, 16> FieldDecls; + for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(), + E = ClassDecl->field_end(); I != E; ++I) { + const FieldDecl *Field = *I; + + QualType FieldType = getContext().getCanonicalType(Field->getType()); + FieldType = getContext().getBaseElementType(FieldType); + + const RecordType *RT = FieldType->getAs<RecordType>(); + if (!RT) + continue; + + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + if (FieldClassDecl->hasTrivialDestructor()) + continue; + + FieldDecls.push_back(Field); + } + + // Now destroy the fields. + for (size_t i = FieldDecls.size(); i > 0; --i) { + const FieldDecl *Field = FieldDecls[i - 1]; + + QualType FieldType = Field->getType(); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(FieldType); + if (Array) + FieldType = getContext().getBaseElementType(FieldType); + + const RecordType *RT = FieldType->getAs<RecordType>(); + CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl()); + + llvm::Value *ThisPtr = LoadCXXThis(); + + LValue LHS = EmitLValueForField(ThisPtr, Field, + // FIXME: Qualifiers? + /*CVRQualifiers=*/0); + if (Array) { + const llvm::Type *BasePtr = ConvertType(FieldType); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(LHS.getAddress(), BasePtr); + EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(getContext()), + Array, BaseAddrPtr); + } else + EmitCXXDestructorCall(FieldClassDecl->getDestructor(getContext()), + Dtor_Complete, /*ForVirtualBase=*/false, + LHS.getAddress()); + } + + // Destroy non-virtual bases. + for (CXXRecordDecl::reverse_base_class_const_iterator I = + ClassDecl->bases_rbegin(), E = ClassDecl->bases_rend(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + + // Ignore virtual bases. + if (Base.isVirtual()) + continue; + + CXXRecordDecl *BaseClassDecl + = cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl()); + + // Ignore trivial destructors. + if (BaseClassDecl->hasTrivialDestructor()) + continue; + + const CXXDestructorDecl *D = BaseClassDecl->getDestructor(getContext()); + llvm::Value *V = + GetAddressOfDirectBaseInCompleteClass(LoadCXXThis(), ClassDecl, + BaseClassDecl, + /*BaseIsVirtual=*/false); + + EmitCXXDestructorCall(D, Dtor_Base, /*ForVirtualBase=*/false, V); + } +} + +/// EmitCXXAggrConstructorCall - This routine essentially creates a (nested) +/// for-loop to call the default constructor on individual members of the +/// array. +/// 'D' is the default constructor for elements of the array, 'ArrayTy' is the +/// array type and 'ArrayPtr' points to the beginning fo the array. +/// It is assumed that all relevant checks have been made by the caller. +void +CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, + const ConstantArrayType *ArrayTy, + llvm::Value *ArrayPtr, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd) { + + const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); + llvm::Value * NumElements = + llvm::ConstantInt::get(SizeTy, + getContext().getConstantArrayElementCount(ArrayTy)); + + EmitCXXAggrConstructorCall(D, NumElements, ArrayPtr, ArgBeg, ArgEnd); +} + +void +CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, + llvm::Value *NumElements, + llvm::Value *ArrayPtr, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd) { + const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); + + // Create a temporary for the loop index and initialize it with 0. + llvm::Value *IndexPtr = CreateTempAlloca(SizeTy, "loop.index"); + llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy); + Builder.CreateStore(Zero, IndexPtr); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + + // Generate: if (loop-index < number-of-elements fall to the loop body, + // otherwise, go to the block after the for-loop. + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsLess = Builder.CreateICmpULT(Counter, NumElements, "isless"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsLess, ForBody, AfterFor); + + EmitBlock(ForBody); + + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *Address = Builder.CreateInBoundsGEP(ArrayPtr, Counter, + "arrayidx"); + + // C++ [class.temporary]p4: + // There are two contexts in which temporaries are destroyed at a different + // point than the end of the full-expression. The first context is when a + // default constructor is called to initialize an element of an array. + // If the constructor has one or more default arguments, the destruction of + // every temporary created in a default argument expression is sequenced + // before the construction of the next array element, if any. + + // Keep track of the current number of live temporaries. + { + CXXTemporariesCleanupScope Scope(*this); + + EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase=*/false, Address, + ArgBeg, ArgEnd); + } + + EmitBlock(ContinueBlock); + + // Emit the increment of the loop counter. + llvm::Value *NextVal = llvm::ConstantInt::get(SizeTy, 1); + Counter = Builder.CreateLoad(IndexPtr); + NextVal = Builder.CreateAdd(Counter, NextVal, "inc"); + Builder.CreateStore(NextVal, IndexPtr); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + +/// EmitCXXAggrDestructorCall - calls the default destructor on array +/// elements in reverse order of construction. +void +CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, + const ArrayType *Array, + llvm::Value *This) { + const ConstantArrayType *CA = dyn_cast<ConstantArrayType>(Array); + assert(CA && "Do we support VLA for destruction ?"); + uint64_t ElementCount = getContext().getConstantArrayElementCount(CA); + + const llvm::Type *SizeLTy = ConvertType(getContext().getSizeType()); + llvm::Value* ElementCountPtr = llvm::ConstantInt::get(SizeLTy, ElementCount); + EmitCXXAggrDestructorCall(D, ElementCountPtr, This); +} + +/// EmitCXXAggrDestructorCall - calls the default destructor on array +/// elements in reverse order of construction. +void +CodeGenFunction::EmitCXXAggrDestructorCall(const CXXDestructorDecl *D, + llvm::Value *UpperCount, + llvm::Value *This) { + const llvm::Type *SizeLTy = ConvertType(getContext().getSizeType()); + llvm::Value *One = llvm::ConstantInt::get(SizeLTy, 1); + + // Create a temporary for the loop index and initialize it with count of + // array elements. + llvm::Value *IndexPtr = CreateTempAlloca(SizeLTy, "loop.index"); + + // Store the number of elements in the index pointer. + Builder.CreateStore(UpperCount, IndexPtr); + + // Start the loop with a block that tests the condition. + llvm::BasicBlock *CondBlock = createBasicBlock("for.cond"); + llvm::BasicBlock *AfterFor = createBasicBlock("for.end"); + + EmitBlock(CondBlock); + + llvm::BasicBlock *ForBody = createBasicBlock("for.body"); + + // Generate: if (loop-index != 0 fall to the loop body, + // otherwise, go to the block after the for-loop. + llvm::Value* zeroConstant = + llvm::Constant::getNullValue(SizeLTy); + llvm::Value *Counter = Builder.CreateLoad(IndexPtr); + llvm::Value *IsNE = Builder.CreateICmpNE(Counter, zeroConstant, + "isne"); + // If the condition is true, execute the body. + Builder.CreateCondBr(IsNE, ForBody, AfterFor); + + EmitBlock(ForBody); + + llvm::BasicBlock *ContinueBlock = createBasicBlock("for.inc"); + // Inside the loop body, emit the constructor call on the array element. + Counter = Builder.CreateLoad(IndexPtr); + Counter = Builder.CreateSub(Counter, One); + llvm::Value *Address = Builder.CreateInBoundsGEP(This, Counter, "arrayidx"); + EmitCXXDestructorCall(D, Dtor_Complete, /*ForVirtualBase=*/false, Address); + + EmitBlock(ContinueBlock); + + // Emit the decrement of the loop counter. + Counter = Builder.CreateLoad(IndexPtr); + Counter = Builder.CreateSub(Counter, One, "dec"); + Builder.CreateStore(Counter, IndexPtr); + + // Finally, branch back up to the condition for the next iteration. + EmitBranch(CondBlock); + + // Emit the fall-through block. + EmitBlock(AfterFor, true); +} + +/// GenerateCXXAggrDestructorHelper - Generates a helper function which when +/// invoked, calls the default destructor on array elements in reverse order of +/// construction. +llvm::Constant * +CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, + const ArrayType *Array, + llvm::Value *This) { + FunctionArgList Args; + ImplicitParamDecl *Dst = + ImplicitParamDecl::Create(getContext(), 0, + SourceLocation(), 0, + getContext().getPointerType(getContext().VoidTy)); + Args.push_back(std::make_pair(Dst, Dst->getType())); + + llvm::SmallString<16> Name; + llvm::raw_svector_ostream(Name) << "__tcf_" << (++UniqueAggrDestructorCount); + QualType R = getContext().VoidTy; + const CGFunctionInfo &FI + = CGM.getTypes().getFunctionInfo(R, Args, FunctionType::ExtInfo()); + const llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI, false); + llvm::Function *Fn = + llvm::Function::Create(FTy, llvm::GlobalValue::InternalLinkage, + Name.str(), + &CGM.getModule()); + IdentifierInfo *II = &CGM.getContext().Idents.get(Name.str()); + FunctionDecl *FD = FunctionDecl::Create(getContext(), + getContext().getTranslationUnitDecl(), + SourceLocation(), II, R, 0, + FunctionDecl::Static, + FunctionDecl::None, + false, true); + StartFunction(FD, R, Fn, Args, SourceLocation()); + QualType BaseElementTy = getContext().getBaseElementType(Array); + const llvm::Type *BasePtr = ConvertType(BaseElementTy); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = Builder.CreateBitCast(This, BasePtr); + EmitCXXAggrDestructorCall(D, Array, BaseAddrPtr); + FinishFunction(); + llvm::Type *Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), + 0); + llvm::Constant *m = llvm::ConstantExpr::getBitCast(Fn, Ptr8Ty); + return m; +} + + +void +CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, + CXXCtorType Type, bool ForVirtualBase, + llvm::Value *This, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd) { + if (D->isTrivial()) { + if (ArgBeg == ArgEnd) { + // Trivial default constructor, no codegen required. + assert(D->isDefaultConstructor() && + "trivial 0-arg ctor not a default ctor"); + return; + } + + assert(ArgBeg + 1 == ArgEnd && "unexpected argcount for trivial ctor"); + assert(D->isCopyConstructor() && "trivial 1-arg ctor not a copy ctor"); + + const Expr *E = (*ArgBeg); + QualType Ty = E->getType(); + llvm::Value *Src = EmitLValue(E).getAddress(); + EmitAggregateCopy(This, Src, Ty); + return; + } + + llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type), ForVirtualBase); + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); + + EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd); +} + +void +CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, + CXXCtorType CtorType, + const FunctionArgList &Args) { + CallArgList DelegateArgs; + + FunctionArgList::const_iterator I = Args.begin(), E = Args.end(); + assert(I != E && "no parameters to constructor"); + + // this + DelegateArgs.push_back(std::make_pair(RValue::get(LoadCXXThis()), + I->second)); + ++I; + + // vtt + if (llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(Ctor, CtorType), + /*ForVirtualBase=*/false)) { + QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy); + DelegateArgs.push_back(std::make_pair(RValue::get(VTT), VoidPP)); + + if (CodeGenVTables::needsVTTParameter(CurGD)) { + assert(I != E && "cannot skip vtt parameter, already done with args"); + assert(I->second == VoidPP && "skipping parameter not of vtt type"); + ++I; + } + } + + // Explicit arguments. + for (; I != E; ++I) { + const VarDecl *Param = I->first; + QualType ArgType = Param->getType(); // because we're passing it to itself + RValue Arg = EmitDelegateCallArg(Param); + + DelegateArgs.push_back(std::make_pair(Arg, ArgType)); + } + + EmitCall(CGM.getTypes().getFunctionInfo(Ctor, CtorType), + CGM.GetAddrOfCXXConstructor(Ctor, CtorType), + ReturnValueSlot(), DelegateArgs, Ctor); +} + +void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, + CXXDtorType Type, + bool ForVirtualBase, + llvm::Value *This) { + llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type), + ForVirtualBase); + llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type); + + EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0); +} + +llvm::Value * +CodeGenFunction::GetVirtualBaseClassOffset(llvm::Value *This, + const CXXRecordDecl *ClassDecl, + const CXXRecordDecl *BaseClassDecl) { + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8Ty(VMContext)->getPointerTo(); + + llvm::Value *VTablePtr = Builder.CreateBitCast(This, + Int8PtrTy->getPointerTo()); + VTablePtr = Builder.CreateLoad(VTablePtr, "vtable"); + + int64_t VBaseOffsetOffset = + CGM.getVTables().getVirtualBaseOffsetOffset(ClassDecl, BaseClassDecl); + + llvm::Value *VBaseOffsetPtr = + Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetOffset, "vbase.offset.ptr"); + const llvm::Type *PtrDiffTy = + ConvertType(getContext().getPointerDiffType()); + + VBaseOffsetPtr = Builder.CreateBitCast(VBaseOffsetPtr, + PtrDiffTy->getPointerTo()); + + llvm::Value *VBaseOffset = Builder.CreateLoad(VBaseOffsetPtr, "vbase.offset"); + + return VBaseOffset; +} + +void +CodeGenFunction::InitializeVTablePointer(BaseSubobject Base, + const CXXRecordDecl *NearestVBase, + uint64_t OffsetFromNearestVBase, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass) { + const CXXRecordDecl *RD = Base.getBase(); + + // Compute the address point. + llvm::Value *VTableAddressPoint; + + // Check if we need to use a vtable from the VTT. + if (CodeGenVTables::needsVTTParameter(CurGD) && + (RD->getNumVBases() || NearestVBase)) { + // Get the secondary vpointer index. + uint64_t VirtualPointerIndex = + CGM.getVTables().getSecondaryVirtualPointerIndex(VTableClass, Base); + + /// Load the VTT. + llvm::Value *VTT = LoadCXXVTT(); + if (VirtualPointerIndex) + VTT = Builder.CreateConstInBoundsGEP1_64(VTT, VirtualPointerIndex); + + // And load the address point from the VTT. + VTableAddressPoint = Builder.CreateLoad(VTT); + } else { + uint64_t AddressPoint = CGM.getVTables().getAddressPoint(Base, VTableClass); + VTableAddressPoint = + Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint); + } + + // Compute where to store the address point. + llvm::Value *VirtualOffset = 0; + uint64_t NonVirtualOffset = 0; + + if (CodeGenVTables::needsVTTParameter(CurGD) && NearestVBase) { + // We need to use the virtual base offset offset because the virtual base + // might have a different offset in the most derived class. + VirtualOffset = GetVirtualBaseClassOffset(LoadCXXThis(), VTableClass, + NearestVBase); + NonVirtualOffset = OffsetFromNearestVBase / 8; + } else { + // We can just use the base offset in the complete class. + NonVirtualOffset = Base.getBaseOffset() / 8; + } + + // Apply the offsets. + llvm::Value *VTableField = LoadCXXThis(); + + if (NonVirtualOffset || VirtualOffset) + VTableField = ApplyNonVirtualAndVirtualOffset(*this, VTableField, + NonVirtualOffset, + VirtualOffset); + + // Finally, store the address point. + const llvm::Type *AddressPointPtrTy = + VTableAddressPoint->getType()->getPointerTo(); + VTableField = Builder.CreateBitCast(VTableField, AddressPointPtrTy); + Builder.CreateStore(VTableAddressPoint, VTableField); +} + +void +CodeGenFunction::InitializeVTablePointers(BaseSubobject Base, + const CXXRecordDecl *NearestVBase, + uint64_t OffsetFromNearestVBase, + bool BaseIsNonVirtualPrimaryBase, + llvm::Constant *VTable, + const CXXRecordDecl *VTableClass, + VisitedVirtualBasesSetTy& VBases) { + // If this base is a non-virtual primary base the address point has already + // been set. + if (!BaseIsNonVirtualPrimaryBase) { + // Initialize the vtable pointer for this base. + InitializeVTablePointer(Base, NearestVBase, OffsetFromNearestVBase, + VTable, VTableClass); + } + + const CXXRecordDecl *RD = Base.getBase(); + + // Traverse bases. + for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), + E = RD->bases_end(); I != E; ++I) { + CXXRecordDecl *BaseDecl + = cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl()); + + // Ignore classes without a vtable. + if (!BaseDecl->isDynamicClass()) + continue; + + uint64_t BaseOffset; + uint64_t BaseOffsetFromNearestVBase; + bool BaseDeclIsNonVirtualPrimaryBase; + + if (I->isVirtual()) { + // Check if we've visited this virtual base before. + if (!VBases.insert(BaseDecl)) + continue; + + const ASTRecordLayout &Layout = + getContext().getASTRecordLayout(VTableClass); + + BaseOffset = Layout.getVBaseClassOffset(BaseDecl); + BaseOffsetFromNearestVBase = 0; + BaseDeclIsNonVirtualPrimaryBase = false; + } else { + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + + BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl); + BaseOffsetFromNearestVBase = + OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl); + BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl; + } + + InitializeVTablePointers(BaseSubobject(BaseDecl, BaseOffset), + I->isVirtual() ? BaseDecl : NearestVBase, + BaseOffsetFromNearestVBase, + BaseDeclIsNonVirtualPrimaryBase, + VTable, VTableClass, VBases); + } +} + +void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) { + // Ignore classes without a vtable. + if (!RD->isDynamicClass()) + return; + + // Get the VTable. + llvm::Constant *VTable = CGM.getVTables().GetAddrOfVTable(RD); + + // Initialize the vtable pointers for this class and all of its bases. + VisitedVirtualBasesSetTy VBases; + InitializeVTablePointers(BaseSubobject(RD, 0), /*NearestVBase=*/0, + /*OffsetFromNearestVBase=*/0, + /*BaseIsNonVirtualPrimaryBase=*/false, + VTable, RD, VBases); +} |