From: Anders Carlsson Date: Fri, 1 Jan 2010 20:29:01 +0000 (+0000) Subject: Move a few more functions away from CGCXX and to CGClass and CGExprCXX. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3b5ad2283c999f6edf7d42332a655447b7386b2e;p=clang Move a few more functions away from CGCXX and to CGClass and CGExprCXX. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92399 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index cc006d9dd6..4323f84d96 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -26,269 +26,7 @@ using namespace clang; using namespace CodeGen; -RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, - llvm::Value *Callee, - ReturnValueSlot ReturnValue, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd) { - assert(MD->isInstance() && - "Trying to emit a member call expr on a static method!"); - const FunctionProtoType *FPT = MD->getType()->getAs(); - - CallArgList Args; - - // Push the this ptr. - Args.push_back(std::make_pair(RValue::get(This), - MD->getThisType(getContext()))); - - // And the rest of the call args - EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); - - QualType ResultType = MD->getType()->getAs()->getResultType(); - return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, - ReturnValue, Args, MD); -} - -/// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given -/// expr can be devirtualized. -static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) { - if (const DeclRefExpr *DRE = dyn_cast(Base)) { - if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { - // This is a record decl. We know the type and can devirtualize it. - return VD->getType()->isRecordType(); - } - - return false; - } - - // We can always devirtualize calls on temporary object expressions. - if (isa(Base)) - return true; - - // And calls on bound temporaries. - if (isa(Base)) - return true; - - // Check if this is a call expr that returns a record type. - if (const CallExpr *CE = dyn_cast(Base)) - return CE->getCallReturnType()->isRecordType(); - - // We can't devirtualize the call. - return false; -} - -RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, - ReturnValueSlot ReturnValue) { - if (isa(CE->getCallee()->IgnoreParens())) - return EmitCXXMemberPointerCallExpr(CE, ReturnValue); - - const MemberExpr *ME = cast(CE->getCallee()->IgnoreParens()); - const CXXMethodDecl *MD = cast(ME->getMemberDecl()); - - if (MD->isStatic()) { - // The method is static, emit it as we would a regular call. - llvm::Value *Callee = CGM.GetAddrOfFunction(MD); - return EmitCall(getContext().getPointerType(MD->getType()), Callee, - ReturnValue, CE->arg_begin(), CE->arg_end()); - } - - const FunctionProtoType *FPT = MD->getType()->getAs(); - - const llvm::Type *Ty = - CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), - FPT->isVariadic()); - llvm::Value *This; - - if (ME->isArrow()) - This = EmitScalarExpr(ME->getBase()); - else { - LValue BaseLV = EmitLValue(ME->getBase()); - This = BaseLV.getAddress(); - } - - if (MD->isCopyAssignment() && MD->isTrivial()) { - // We don't like to generate the trivial copy assignment operator when - // it isn't necessary; just produce the proper effect here. - llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress(); - EmitAggregateCopy(This, RHS, CE->getType()); - return RValue::get(This); - } - - // C++ [class.virtual]p12: - // Explicit qualification with the scope operator (5.1) suppresses the - // virtual call mechanism. - // - // We also don't emit a virtual call if the base expression has a record type - // because then we know what the type is. - llvm::Value *Callee; - if (const CXXDestructorDecl *Destructor - = dyn_cast(MD)) { - if (Destructor->isTrivial()) - return RValue::get(0); - if (MD->isVirtual() && !ME->hasQualifier() && - !canDevirtualizeMemberFunctionCalls(ME->getBase())) { - Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty); - } else { - Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); - } - } else if (MD->isVirtual() && !ME->hasQualifier() && - !canDevirtualizeMemberFunctionCalls(ME->getBase())) { - Callee = BuildVirtualCall(MD, This, Ty); - } else { - Callee = CGM.GetAddrOfFunction(MD, Ty); - } - - return EmitCXXMemberCall(MD, Callee, ReturnValue, This, - CE->arg_begin(), CE->arg_end()); -} - -RValue -CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, - ReturnValueSlot ReturnValue) { - const BinaryOperator *BO = - cast(E->getCallee()->IgnoreParens()); - const Expr *BaseExpr = BO->getLHS(); - const Expr *MemFnExpr = BO->getRHS(); - - const MemberPointerType *MPT = - MemFnExpr->getType()->getAs(); - const FunctionProtoType *FPT = - MPT->getPointeeType()->getAs(); - const CXXRecordDecl *RD = - cast(MPT->getClass()->getAs()->getDecl()); - - const llvm::FunctionType *FTy = - CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), - FPT->isVariadic()); - - const llvm::Type *Int8PtrTy = - llvm::Type::getInt8Ty(VMContext)->getPointerTo(); - - // Get the member function pointer. - llvm::Value *MemFnPtr = - CreateTempAlloca(ConvertType(MemFnExpr->getType()), "mem.fn"); - EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false); - - // Emit the 'this' pointer. - llvm::Value *This; - - if (BO->getOpcode() == BinaryOperator::PtrMemI) - This = EmitScalarExpr(BaseExpr); - else - This = EmitLValue(BaseExpr).getAddress(); - - // Adjust it. - llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1); - Adj = Builder.CreateLoad(Adj, "mem.fn.adj"); - - llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr"); - Ptr = Builder.CreateGEP(Ptr, Adj, "adj"); - - This = Builder.CreateBitCast(Ptr, This->getType(), "this"); - - llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr"); - - const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); - - llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn"); - - // If the LSB in the function pointer is 1, the function pointer points to - // a virtual function. - llvm::Value *IsVirtual - = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1), - "and"); - - IsVirtual = Builder.CreateTrunc(IsVirtual, - llvm::Type::getInt1Ty(VMContext)); - - llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual"); - llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual"); - llvm::BasicBlock *FnEnd = createBasicBlock("fn.end"); - - Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); - EmitBlock(FnVirtual); - - const llvm::Type *VTableTy = - FTy->getPointerTo()->getPointerTo()->getPointerTo(); - - llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy); - VTable = Builder.CreateLoad(VTable); - - VTable = Builder.CreateGEP(VTable, FnAsInt, "fn"); - - // Since the function pointer is 1 plus the virtual table offset, we - // subtract 1 by using a GEP. - VTable = Builder.CreateConstGEP1_64(VTable, (uint64_t)-1); - - llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn"); - - EmitBranch(FnEnd); - EmitBlock(FnNonVirtual); - - // If the function is not virtual, just load the pointer. - llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn"); - NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo()); - - EmitBlock(FnEnd); - - llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo()); - Callee->reserveOperandSpace(2); - Callee->addIncoming(VirtualFn, FnVirtual); - Callee->addIncoming(NonVirtualFn, FnNonVirtual); - - CallArgList Args; - - QualType ThisType = - getContext().getPointerType(getContext().getTagDeclType(RD)); - - // Push the this ptr. - Args.push_back(std::make_pair(RValue::get(This), ThisType)); - - // And the rest of the call args - EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); - QualType ResultType = BO->getType()->getAs()->getResultType(); - return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, - ReturnValue, Args); -} - -RValue -CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, - const CXXMethodDecl *MD, - ReturnValueSlot ReturnValue) { - assert(MD->isInstance() && - "Trying to emit a member call expr on a static method!"); - - if (MD->isCopyAssignment()) { - const CXXRecordDecl *ClassDecl = cast(MD->getDeclContext()); - if (ClassDecl->hasTrivialCopyAssignment()) { - assert(!ClassDecl->hasUserDeclaredCopyAssignment() && - "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); - llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); - llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); - QualType Ty = E->getType(); - EmitAggregateCopy(This, Src, Ty); - return RValue::get(This); - } - } - - const FunctionProtoType *FPT = MD->getType()->getAs(); - const llvm::Type *Ty = - CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), - FPT->isVariadic()); - - llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); - - llvm::Value *Callee; - if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0))) - Callee = BuildVirtualCall(MD, This, Ty); - else - Callee = CGM.GetAddrOfFunction(MD, Ty); - - return EmitCXXMemberCall(MD, Callee, ReturnValue, This, - E->arg_begin() + 1, E->arg_end()); -} llvm::Value *CodeGenFunction::LoadCXXThis() { assert(isa(CurFuncDecl) && @@ -302,320 +40,6 @@ llvm::Value *CodeGenFunction::LoadCXXThis() { return Builder.CreateLoad(LocalDeclMap[CXXThisDecl], "this"); } -/// 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. - unsigned OldNumLiveTemporaries = LiveTemporaries.size(); - - EmitCXXConstructorCall(D, Ctor_Complete, Address, ArgBeg, ArgEnd); - - // Pop temporaries. - while (LiveTemporaries.size() > OldNumLiveTemporaries) - PopCXXTemporary(); - - 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(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, 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); - 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, - 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, - llvm::Value *This, - CallExpr::const_arg_iterator ArgBeg, - CallExpr::const_arg_iterator ArgEnd) { - if (D->isCopyConstructor()) { - const CXXRecordDecl *ClassDecl = cast(D->getDeclContext()); - if (ClassDecl->hasTrivialCopyConstructor()) { - assert(!ClassDecl->hasUserDeclaredCopyConstructor() && - "EmitCXXConstructorCall - user declared copy constructor"); - const Expr *E = (*ArgBeg); - QualType Ty = E->getType(); - llvm::Value *Src = EmitLValue(E).getAddress(); - EmitAggregateCopy(This, Src, Ty); - return; - } - } else if (D->isTrivial()) { - // FIXME: Track down why we're trying to generate calls to the trivial - // default constructor! - return; - } - - llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); - - EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, ArgBeg, ArgEnd); -} - -void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, - CXXDtorType Type, - llvm::Value *This) { - llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type); - - CallArgList Args; - - // Push the this ptr. - Args.push_back(std::make_pair(RValue::get(This), - DD->getThisType(getContext()))); - - // Add a VTT parameter if necessary. - // FIXME: This should not be a dummy null parameter! - if (Type == Dtor_Base && DD->getParent()->getNumVBases() != 0) { - QualType T = getContext().getPointerType(getContext().VoidPtrTy); - - Args.push_back(std::make_pair(RValue::get(CGM.EmitNullConstant(T)), T)); - } - - // FIXME: We should try to share this code with EmitCXXMemberCall. - - QualType ResultType = DD->getType()->getAs()->getResultType(); - EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, - ReturnValueSlot(), Args, DD); -} - -void -CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, - const CXXConstructExpr *E) { - assert(Dest && "Must have a destination!"); - const CXXConstructorDecl *CD = E->getConstructor(); - const ConstantArrayType *Array = - getContext().getAsConstantArrayType(E->getType()); - // For a copy constructor, even if it is trivial, must fall thru so - // its argument is code-gen'ed. - if (!CD->isCopyConstructor()) { - QualType InitType = E->getType(); - if (Array) - InitType = getContext().getBaseElementType(Array); - const CXXRecordDecl *RD = - cast(InitType->getAs()->getDecl()); - if (RD->hasTrivialConstructor()) - return; - } - // Code gen optimization to eliminate copy constructor and return - // its first argument instead. - if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { - const Expr *Arg = E->getArg(0); - - if (const ImplicitCastExpr *ICE = dyn_cast(Arg)) { - assert((ICE->getCastKind() == CastExpr::CK_NoOp || - ICE->getCastKind() == CastExpr::CK_ConstructorConversion || - ICE->getCastKind() == CastExpr::CK_UserDefinedConversion) && - "Unknown implicit cast kind in constructor elision"); - Arg = ICE->getSubExpr(); - } - - if (const CXXFunctionalCastExpr *FCE = dyn_cast(Arg)) - Arg = FCE->getSubExpr(); - - if (const CXXBindTemporaryExpr *BindExpr = - dyn_cast(Arg)) - Arg = BindExpr->getSubExpr(); - - EmitAggExpr(Arg, Dest, false); - return; - } - if (Array) { - QualType BaseElementTy = getContext().getBaseElementType(Array); - const llvm::Type *BasePtr = ConvertType(BaseElementTy); - BasePtr = llvm::PointerType::getUnqual(BasePtr); - llvm::Value *BaseAddrPtr = - Builder.CreateBitCast(Dest, BasePtr); - - EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, - E->arg_begin(), E->arg_end()); - } - else - // Call the constructor. - EmitCXXConstructorCall(CD, Ctor_Complete, Dest, - E->arg_begin(), E->arg_end()); -} - void CodeGenModule::EmitCXXConstructors(const CXXConstructorDecl *D) { EmitGlobal(GlobalDecl(D, Ctor_Complete)); EmitGlobal(GlobalDecl(D, Ctor_Base)); @@ -1001,33 +425,6 @@ CodeGenModule::BuildCovariantThunk(const GlobalDecl &GD, bool Extern, return m; } -llvm::Value * -CodeGenFunction::GetVirtualCXXBaseClassOffset(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 VBaseOffsetIndex = - CGM.getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl); - - llvm::Value *VBaseOffsetPtr = - Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "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; -} - static llvm::Value *BuildVirtualCall(CodeGenFunction &CGF, uint64_t VtableIndex, llvm::Value *This, const llvm::Type *Ty) { Ty = Ty->getPointerTo()->getPointerTo()->getPointerTo(); @@ -1058,71 +455,3 @@ CodeGenFunction::BuildVirtualCall(const CXXDestructorDecl *DD, CXXDtorType Type, return ::BuildVirtualCall(*this, VtableIndex, This, Ty); } - -void CodeGenFunction::InitializeVtablePtrs(const CXXRecordDecl *ClassDecl) { - if (!ClassDecl->isDynamicClass()) - return; - - llvm::Constant *Vtable = CGM.getVtableInfo().getVtable(ClassDecl); - CodeGenModule::AddrSubMap_t& AddressPoints = - *(*CGM.AddressPoints[ClassDecl])[ClassDecl]; - llvm::Value *ThisPtr = LoadCXXThis(); - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); - - // Store address points for virtual bases - for (CXXRecordDecl::base_class_const_iterator I = - ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); I != E; ++I) { - const CXXBaseSpecifier &Base = *I; - CXXRecordDecl *BaseClassDecl - = cast(Base.getType()->getAs()->getDecl()); - uint64_t Offset = Layout.getVBaseClassOffset(BaseClassDecl); - InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, - ThisPtr, Offset); - } - - // Store address points for non-virtual bases and current class - InitializeVtablePtrsRecursive(ClassDecl, Vtable, AddressPoints, ThisPtr, 0); -} - -void CodeGenFunction::InitializeVtablePtrsRecursive( - const CXXRecordDecl *ClassDecl, - llvm::Constant *Vtable, - CodeGenModule::AddrSubMap_t& AddressPoints, - llvm::Value *ThisPtr, - uint64_t Offset) { - if (!ClassDecl->isDynamicClass()) - return; - - // Store address points for non-virtual bases - const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); - for (CXXRecordDecl::base_class_const_iterator I = - ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) { - const CXXBaseSpecifier &Base = *I; - if (Base.isVirtual()) - continue; - CXXRecordDecl *BaseClassDecl - = cast(Base.getType()->getAs()->getDecl()); - uint64_t NewOffset = Offset + Layout.getBaseClassOffset(BaseClassDecl); - InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, - ThisPtr, NewOffset); - } - - // Compute the address point - assert(AddressPoints.count(std::make_pair(ClassDecl, Offset)) && - "Missing address point for class"); - uint64_t AddressPoint = AddressPoints[std::make_pair(ClassDecl, Offset)]; - llvm::Value *VtableAddressPoint = - Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint); - - // Compute the address to store the address point - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - llvm::Value *VtableField = Builder.CreateBitCast(ThisPtr, Int8PtrTy); - VtableField = Builder.CreateConstInBoundsGEP1_64(VtableField, Offset/8); - const llvm::Type *AddressPointPtrTy = - VtableAddressPoint->getType()->getPointerTo(); - VtableField = Builder.CreateBitCast(VtableField, AddressPointPtrTy); - - // Store address point - Builder.CreateStore(VtableAddressPoint, VtableField); -} - diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 953b8c89dd..b4f964fb5c 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -1044,3 +1044,354 @@ void CodeGenFunction::SynthesizeDefaultDestructor(const CXXDestructorDecl *Dtor, EmitDtorEpilogue(Dtor, DtorType); FinishFunction(); } + +/// 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. + unsigned OldNumLiveTemporaries = LiveTemporaries.size(); + + EmitCXXConstructorCall(D, Ctor_Complete, Address, ArgBeg, ArgEnd); + + // Pop temporaries. + while (LiveTemporaries.size() > OldNumLiveTemporaries) + PopCXXTemporary(); + + 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(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, 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); + 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, + 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, + llvm::Value *This, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd) { + if (D->isCopyConstructor()) { + const CXXRecordDecl *ClassDecl = cast(D->getDeclContext()); + if (ClassDecl->hasTrivialCopyConstructor()) { + assert(!ClassDecl->hasUserDeclaredCopyConstructor() && + "EmitCXXConstructorCall - user declared copy constructor"); + const Expr *E = (*ArgBeg); + QualType Ty = E->getType(); + llvm::Value *Src = EmitLValue(E).getAddress(); + EmitAggregateCopy(This, Src, Ty); + return; + } + } else if (D->isTrivial()) { + // FIXME: Track down why we're trying to generate calls to the trivial + // default constructor! + return; + } + + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); + + EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, ArgBeg, ArgEnd); +} + +void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, + CXXDtorType Type, + llvm::Value *This) { + llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type); + + CallArgList Args; + + // Push the this ptr. + Args.push_back(std::make_pair(RValue::get(This), + DD->getThisType(getContext()))); + + // Add a VTT parameter if necessary. + // FIXME: This should not be a dummy null parameter! + if (Type == Dtor_Base && DD->getParent()->getNumVBases() != 0) { + QualType T = getContext().getPointerType(getContext().VoidPtrTy); + + Args.push_back(std::make_pair(RValue::get(CGM.EmitNullConstant(T)), T)); + } + + // FIXME: We should try to share this code with EmitCXXMemberCall. + + QualType ResultType = DD->getType()->getAs()->getResultType(); + EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, + ReturnValueSlot(), Args, DD); +} + +llvm::Value * +CodeGenFunction::GetVirtualCXXBaseClassOffset(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 VBaseOffsetIndex = + CGM.getVtableInfo().getVirtualBaseOffsetIndex(ClassDecl, BaseClassDecl); + + llvm::Value *VBaseOffsetPtr = + Builder.CreateConstGEP1_64(VTablePtr, VBaseOffsetIndex, "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::InitializeVtablePtrs(const CXXRecordDecl *ClassDecl) { + if (!ClassDecl->isDynamicClass()) + return; + + llvm::Constant *Vtable = CGM.getVtableInfo().getVtable(ClassDecl); + CodeGenModule::AddrSubMap_t& AddressPoints = + *(*CGM.AddressPoints[ClassDecl])[ClassDecl]; + llvm::Value *ThisPtr = LoadCXXThis(); + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); + + // Store address points for virtual bases + for (CXXRecordDecl::base_class_const_iterator I = + ClassDecl->vbases_begin(), E = ClassDecl->vbases_end(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + CXXRecordDecl *BaseClassDecl + = cast(Base.getType()->getAs()->getDecl()); + uint64_t Offset = Layout.getVBaseClassOffset(BaseClassDecl); + InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, + ThisPtr, Offset); + } + + // Store address points for non-virtual bases and current class + InitializeVtablePtrsRecursive(ClassDecl, Vtable, AddressPoints, ThisPtr, 0); +} + +void CodeGenFunction::InitializeVtablePtrsRecursive( + const CXXRecordDecl *ClassDecl, + llvm::Constant *Vtable, + CodeGenModule::AddrSubMap_t& AddressPoints, + llvm::Value *ThisPtr, + uint64_t Offset) { + if (!ClassDecl->isDynamicClass()) + return; + + // Store address points for non-virtual bases + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl); + for (CXXRecordDecl::base_class_const_iterator I = + ClassDecl->bases_begin(), E = ClassDecl->bases_end(); I != E; ++I) { + const CXXBaseSpecifier &Base = *I; + if (Base.isVirtual()) + continue; + CXXRecordDecl *BaseClassDecl + = cast(Base.getType()->getAs()->getDecl()); + uint64_t NewOffset = Offset + Layout.getBaseClassOffset(BaseClassDecl); + InitializeVtablePtrsRecursive(BaseClassDecl, Vtable, AddressPoints, + ThisPtr, NewOffset); + } + + // Compute the address point + assert(AddressPoints.count(std::make_pair(ClassDecl, Offset)) && + "Missing address point for class"); + uint64_t AddressPoint = AddressPoints[std::make_pair(ClassDecl, Offset)]; + llvm::Value *VtableAddressPoint = + Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint); + + // Compute the address to store the address point + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); + llvm::Value *VtableField = Builder.CreateBitCast(ThisPtr, Int8PtrTy); + VtableField = Builder.CreateConstInBoundsGEP1_64(VtableField, Offset/8); + const llvm::Type *AddressPointPtrTy = + VtableAddressPoint->getType()->getPointerTo(); + VtableField = Builder.CreateBitCast(VtableField, AddressPointPtrTy); + + // Store address point + Builder.CreateStore(VtableAddressPoint, VtableField); +} diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 7992322196..a36e92559b 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -15,6 +15,327 @@ using namespace clang; using namespace CodeGen; +RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, + llvm::Value *Callee, + ReturnValueSlot ReturnValue, + llvm::Value *This, + CallExpr::const_arg_iterator ArgBeg, + CallExpr::const_arg_iterator ArgEnd) { + assert(MD->isInstance() && + "Trying to emit a member call expr on a static method!"); + + const FunctionProtoType *FPT = MD->getType()->getAs(); + + CallArgList Args; + + // Push the this ptr. + Args.push_back(std::make_pair(RValue::get(This), + MD->getThisType(getContext()))); + + // And the rest of the call args + EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); + + QualType ResultType = MD->getType()->getAs()->getResultType(); + return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, + ReturnValue, Args, MD); +} + +/// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given +/// expr can be devirtualized. +static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) { + if (const DeclRefExpr *DRE = dyn_cast(Base)) { + if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { + // This is a record decl. We know the type and can devirtualize it. + return VD->getType()->isRecordType(); + } + + return false; + } + + // We can always devirtualize calls on temporary object expressions. + if (isa(Base)) + return true; + + // And calls on bound temporaries. + if (isa(Base)) + return true; + + // Check if this is a call expr that returns a record type. + if (const CallExpr *CE = dyn_cast(Base)) + return CE->getCallReturnType()->isRecordType(); + + // We can't devirtualize the call. + return false; +} + +RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, + ReturnValueSlot ReturnValue) { + if (isa(CE->getCallee()->IgnoreParens())) + return EmitCXXMemberPointerCallExpr(CE, ReturnValue); + + const MemberExpr *ME = cast(CE->getCallee()->IgnoreParens()); + const CXXMethodDecl *MD = cast(ME->getMemberDecl()); + + if (MD->isStatic()) { + // The method is static, emit it as we would a regular call. + llvm::Value *Callee = CGM.GetAddrOfFunction(MD); + return EmitCall(getContext().getPointerType(MD->getType()), Callee, + ReturnValue, CE->arg_begin(), CE->arg_end()); + } + + const FunctionProtoType *FPT = MD->getType()->getAs(); + + const llvm::Type *Ty = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + llvm::Value *This; + + if (ME->isArrow()) + This = EmitScalarExpr(ME->getBase()); + else { + LValue BaseLV = EmitLValue(ME->getBase()); + This = BaseLV.getAddress(); + } + + if (MD->isCopyAssignment() && MD->isTrivial()) { + // We don't like to generate the trivial copy assignment operator when + // it isn't necessary; just produce the proper effect here. + llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress(); + EmitAggregateCopy(This, RHS, CE->getType()); + return RValue::get(This); + } + + // C++ [class.virtual]p12: + // Explicit qualification with the scope operator (5.1) suppresses the + // virtual call mechanism. + // + // We also don't emit a virtual call if the base expression has a record type + // because then we know what the type is. + llvm::Value *Callee; + if (const CXXDestructorDecl *Destructor + = dyn_cast(MD)) { + if (Destructor->isTrivial()) + return RValue::get(0); + if (MD->isVirtual() && !ME->hasQualifier() && + !canDevirtualizeMemberFunctionCalls(ME->getBase())) { + Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty); + } else { + Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); + } + } else if (MD->isVirtual() && !ME->hasQualifier() && + !canDevirtualizeMemberFunctionCalls(ME->getBase())) { + Callee = BuildVirtualCall(MD, This, Ty); + } else { + Callee = CGM.GetAddrOfFunction(MD, Ty); + } + + return EmitCXXMemberCall(MD, Callee, ReturnValue, This, + CE->arg_begin(), CE->arg_end()); +} + +RValue +CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, + ReturnValueSlot ReturnValue) { + const BinaryOperator *BO = + cast(E->getCallee()->IgnoreParens()); + const Expr *BaseExpr = BO->getLHS(); + const Expr *MemFnExpr = BO->getRHS(); + + const MemberPointerType *MPT = + MemFnExpr->getType()->getAs(); + const FunctionProtoType *FPT = + MPT->getPointeeType()->getAs(); + const CXXRecordDecl *RD = + cast(MPT->getClass()->getAs()->getDecl()); + + const llvm::FunctionType *FTy = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), + FPT->isVariadic()); + + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8Ty(VMContext)->getPointerTo(); + + // Get the member function pointer. + llvm::Value *MemFnPtr = + CreateTempAlloca(ConvertType(MemFnExpr->getType()), "mem.fn"); + EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false); + + // Emit the 'this' pointer. + llvm::Value *This; + + if (BO->getOpcode() == BinaryOperator::PtrMemI) + This = EmitScalarExpr(BaseExpr); + else + This = EmitLValue(BaseExpr).getAddress(); + + // Adjust it. + llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1); + Adj = Builder.CreateLoad(Adj, "mem.fn.adj"); + + llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr"); + Ptr = Builder.CreateGEP(Ptr, Adj, "adj"); + + This = Builder.CreateBitCast(Ptr, This->getType(), "this"); + + llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr"); + + const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); + + llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn"); + + // If the LSB in the function pointer is 1, the function pointer points to + // a virtual function. + llvm::Value *IsVirtual + = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1), + "and"); + + IsVirtual = Builder.CreateTrunc(IsVirtual, + llvm::Type::getInt1Ty(VMContext)); + + llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual"); + llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual"); + llvm::BasicBlock *FnEnd = createBasicBlock("fn.end"); + + Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); + EmitBlock(FnVirtual); + + const llvm::Type *VTableTy = + FTy->getPointerTo()->getPointerTo()->getPointerTo(); + + llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy); + VTable = Builder.CreateLoad(VTable); + + VTable = Builder.CreateGEP(VTable, FnAsInt, "fn"); + + // Since the function pointer is 1 plus the virtual table offset, we + // subtract 1 by using a GEP. + VTable = Builder.CreateConstGEP1_64(VTable, (uint64_t)-1); + + llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn"); + + EmitBranch(FnEnd); + EmitBlock(FnNonVirtual); + + // If the function is not virtual, just load the pointer. + llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn"); + NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo()); + + EmitBlock(FnEnd); + + llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo()); + Callee->reserveOperandSpace(2); + Callee->addIncoming(VirtualFn, FnVirtual); + Callee->addIncoming(NonVirtualFn, FnNonVirtual); + + CallArgList Args; + + QualType ThisType = + getContext().getPointerType(getContext().getTagDeclType(RD)); + + // Push the this ptr. + Args.push_back(std::make_pair(RValue::get(This), ThisType)); + + // And the rest of the call args + EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); + QualType ResultType = BO->getType()->getAs()->getResultType(); + return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, + ReturnValue, Args); +} + +RValue +CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, + const CXXMethodDecl *MD, + ReturnValueSlot ReturnValue) { + assert(MD->isInstance() && + "Trying to emit a member call expr on a static method!"); + + if (MD->isCopyAssignment()) { + const CXXRecordDecl *ClassDecl = cast(MD->getDeclContext()); + if (ClassDecl->hasTrivialCopyAssignment()) { + assert(!ClassDecl->hasUserDeclaredCopyAssignment() && + "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); + llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); + QualType Ty = E->getType(); + EmitAggregateCopy(This, Src, Ty); + return RValue::get(This); + } + } + + const FunctionProtoType *FPT = MD->getType()->getAs(); + const llvm::Type *Ty = + CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), + FPT->isVariadic()); + + llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); + + llvm::Value *Callee; + if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0))) + Callee = BuildVirtualCall(MD, This, Ty); + else + Callee = CGM.GetAddrOfFunction(MD, Ty); + + return EmitCXXMemberCall(MD, Callee, ReturnValue, This, + E->arg_begin() + 1, E->arg_end()); +} + +void +CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, + const CXXConstructExpr *E) { + assert(Dest && "Must have a destination!"); + const CXXConstructorDecl *CD = E->getConstructor(); + const ConstantArrayType *Array = + getContext().getAsConstantArrayType(E->getType()); + // For a copy constructor, even if it is trivial, must fall thru so + // its argument is code-gen'ed. + if (!CD->isCopyConstructor()) { + QualType InitType = E->getType(); + if (Array) + InitType = getContext().getBaseElementType(Array); + const CXXRecordDecl *RD = + cast(InitType->getAs()->getDecl()); + if (RD->hasTrivialConstructor()) + return; + } + // Code gen optimization to eliminate copy constructor and return + // its first argument instead. + if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { + const Expr *Arg = E->getArg(0); + + if (const ImplicitCastExpr *ICE = dyn_cast(Arg)) { + assert((ICE->getCastKind() == CastExpr::CK_NoOp || + ICE->getCastKind() == CastExpr::CK_ConstructorConversion || + ICE->getCastKind() == CastExpr::CK_UserDefinedConversion) && + "Unknown implicit cast kind in constructor elision"); + Arg = ICE->getSubExpr(); + } + + if (const CXXFunctionalCastExpr *FCE = dyn_cast(Arg)) + Arg = FCE->getSubExpr(); + + if (const CXXBindTemporaryExpr *BindExpr = + dyn_cast(Arg)) + Arg = BindExpr->getSubExpr(); + + EmitAggExpr(Arg, Dest, false); + return; + } + if (Array) { + QualType BaseElementTy = getContext().getBaseElementType(Array); + const llvm::Type *BasePtr = ConvertType(BaseElementTy); + BasePtr = llvm::PointerType::getUnqual(BasePtr); + llvm::Value *BaseAddrPtr = + Builder.CreateBitCast(Dest, BasePtr); + + EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, + E->arg_begin(), E->arg_end()); + } + else + // Call the constructor. + EmitCXXConstructorCall(CD, Ctor_Complete, Dest, + E->arg_begin(), E->arg_end()); +} + static uint64_t CalculateCookiePadding(ASTContext &Ctx, QualType ElementType) { const RecordType *RT = ElementType->getAs(); if (!RT) diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 7930f7186d..98fb60a3de 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -161,7 +161,6 @@ private: llvm::DenseMap &subAddressPoints; typedef CXXRecordDecl::method_iterator method_iter; - const bool Extern; const uint32_t LLVMPointerWidth; Index_t extra; typedef std::vector > Path_t; @@ -199,7 +198,6 @@ public: rtti(0), VMContext(cgm.getModule().getContext()),CGM(cgm), PureVirtualFn(0), subAddressPoints(AllocAddressPoint(cgm, l, MostDerivedClass)), - Extern(!l->isInAnonymousNamespace()), LLVMPointerWidth(cgm.getContext().Target.getPointerWidth(0)) { Ptr8Ty = llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); if (BuildVtable) {