159486a2dSAnders Carlsson //===--- CGExprCXX.cpp - Emit LLVM Code for C++ expressions ---------------===// 259486a2dSAnders Carlsson // 359486a2dSAnders Carlsson // The LLVM Compiler Infrastructure 459486a2dSAnders Carlsson // 559486a2dSAnders Carlsson // This file is distributed under the University of Illinois Open Source 659486a2dSAnders Carlsson // License. See LICENSE.TXT for details. 759486a2dSAnders Carlsson // 859486a2dSAnders Carlsson //===----------------------------------------------------------------------===// 959486a2dSAnders Carlsson // 1059486a2dSAnders Carlsson // This contains code dealing with code generation of C++ expressions 1159486a2dSAnders Carlsson // 1259486a2dSAnders Carlsson //===----------------------------------------------------------------------===// 1359486a2dSAnders Carlsson 1459486a2dSAnders Carlsson #include "CodeGenFunction.h" 1559486a2dSAnders Carlsson using namespace clang; 1659486a2dSAnders Carlsson using namespace CodeGen; 1759486a2dSAnders Carlsson 18*27da15baSAnders Carlsson RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, 19*27da15baSAnders Carlsson llvm::Value *Callee, 20*27da15baSAnders Carlsson ReturnValueSlot ReturnValue, 21*27da15baSAnders Carlsson llvm::Value *This, 22*27da15baSAnders Carlsson CallExpr::const_arg_iterator ArgBeg, 23*27da15baSAnders Carlsson CallExpr::const_arg_iterator ArgEnd) { 24*27da15baSAnders Carlsson assert(MD->isInstance() && 25*27da15baSAnders Carlsson "Trying to emit a member call expr on a static method!"); 26*27da15baSAnders Carlsson 27*27da15baSAnders Carlsson const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 28*27da15baSAnders Carlsson 29*27da15baSAnders Carlsson CallArgList Args; 30*27da15baSAnders Carlsson 31*27da15baSAnders Carlsson // Push the this ptr. 32*27da15baSAnders Carlsson Args.push_back(std::make_pair(RValue::get(This), 33*27da15baSAnders Carlsson MD->getThisType(getContext()))); 34*27da15baSAnders Carlsson 35*27da15baSAnders Carlsson // And the rest of the call args 36*27da15baSAnders Carlsson EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); 37*27da15baSAnders Carlsson 38*27da15baSAnders Carlsson QualType ResultType = MD->getType()->getAs<FunctionType>()->getResultType(); 39*27da15baSAnders Carlsson return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, 40*27da15baSAnders Carlsson ReturnValue, Args, MD); 41*27da15baSAnders Carlsson } 42*27da15baSAnders Carlsson 43*27da15baSAnders Carlsson /// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given 44*27da15baSAnders Carlsson /// expr can be devirtualized. 45*27da15baSAnders Carlsson static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) { 46*27da15baSAnders Carlsson if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) { 47*27da15baSAnders Carlsson if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { 48*27da15baSAnders Carlsson // This is a record decl. We know the type and can devirtualize it. 49*27da15baSAnders Carlsson return VD->getType()->isRecordType(); 50*27da15baSAnders Carlsson } 51*27da15baSAnders Carlsson 52*27da15baSAnders Carlsson return false; 53*27da15baSAnders Carlsson } 54*27da15baSAnders Carlsson 55*27da15baSAnders Carlsson // We can always devirtualize calls on temporary object expressions. 56*27da15baSAnders Carlsson if (isa<CXXTemporaryObjectExpr>(Base)) 57*27da15baSAnders Carlsson return true; 58*27da15baSAnders Carlsson 59*27da15baSAnders Carlsson // And calls on bound temporaries. 60*27da15baSAnders Carlsson if (isa<CXXBindTemporaryExpr>(Base)) 61*27da15baSAnders Carlsson return true; 62*27da15baSAnders Carlsson 63*27da15baSAnders Carlsson // Check if this is a call expr that returns a record type. 64*27da15baSAnders Carlsson if (const CallExpr *CE = dyn_cast<CallExpr>(Base)) 65*27da15baSAnders Carlsson return CE->getCallReturnType()->isRecordType(); 66*27da15baSAnders Carlsson 67*27da15baSAnders Carlsson // We can't devirtualize the call. 68*27da15baSAnders Carlsson return false; 69*27da15baSAnders Carlsson } 70*27da15baSAnders Carlsson 71*27da15baSAnders Carlsson RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, 72*27da15baSAnders Carlsson ReturnValueSlot ReturnValue) { 73*27da15baSAnders Carlsson if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens())) 74*27da15baSAnders Carlsson return EmitCXXMemberPointerCallExpr(CE, ReturnValue); 75*27da15baSAnders Carlsson 76*27da15baSAnders Carlsson const MemberExpr *ME = cast<MemberExpr>(CE->getCallee()->IgnoreParens()); 77*27da15baSAnders Carlsson const CXXMethodDecl *MD = cast<CXXMethodDecl>(ME->getMemberDecl()); 78*27da15baSAnders Carlsson 79*27da15baSAnders Carlsson if (MD->isStatic()) { 80*27da15baSAnders Carlsson // The method is static, emit it as we would a regular call. 81*27da15baSAnders Carlsson llvm::Value *Callee = CGM.GetAddrOfFunction(MD); 82*27da15baSAnders Carlsson return EmitCall(getContext().getPointerType(MD->getType()), Callee, 83*27da15baSAnders Carlsson ReturnValue, CE->arg_begin(), CE->arg_end()); 84*27da15baSAnders Carlsson } 85*27da15baSAnders Carlsson 86*27da15baSAnders Carlsson const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 87*27da15baSAnders Carlsson 88*27da15baSAnders Carlsson const llvm::Type *Ty = 89*27da15baSAnders Carlsson CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 90*27da15baSAnders Carlsson FPT->isVariadic()); 91*27da15baSAnders Carlsson llvm::Value *This; 92*27da15baSAnders Carlsson 93*27da15baSAnders Carlsson if (ME->isArrow()) 94*27da15baSAnders Carlsson This = EmitScalarExpr(ME->getBase()); 95*27da15baSAnders Carlsson else { 96*27da15baSAnders Carlsson LValue BaseLV = EmitLValue(ME->getBase()); 97*27da15baSAnders Carlsson This = BaseLV.getAddress(); 98*27da15baSAnders Carlsson } 99*27da15baSAnders Carlsson 100*27da15baSAnders Carlsson if (MD->isCopyAssignment() && MD->isTrivial()) { 101*27da15baSAnders Carlsson // We don't like to generate the trivial copy assignment operator when 102*27da15baSAnders Carlsson // it isn't necessary; just produce the proper effect here. 103*27da15baSAnders Carlsson llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress(); 104*27da15baSAnders Carlsson EmitAggregateCopy(This, RHS, CE->getType()); 105*27da15baSAnders Carlsson return RValue::get(This); 106*27da15baSAnders Carlsson } 107*27da15baSAnders Carlsson 108*27da15baSAnders Carlsson // C++ [class.virtual]p12: 109*27da15baSAnders Carlsson // Explicit qualification with the scope operator (5.1) suppresses the 110*27da15baSAnders Carlsson // virtual call mechanism. 111*27da15baSAnders Carlsson // 112*27da15baSAnders Carlsson // We also don't emit a virtual call if the base expression has a record type 113*27da15baSAnders Carlsson // because then we know what the type is. 114*27da15baSAnders Carlsson llvm::Value *Callee; 115*27da15baSAnders Carlsson if (const CXXDestructorDecl *Destructor 116*27da15baSAnders Carlsson = dyn_cast<CXXDestructorDecl>(MD)) { 117*27da15baSAnders Carlsson if (Destructor->isTrivial()) 118*27da15baSAnders Carlsson return RValue::get(0); 119*27da15baSAnders Carlsson if (MD->isVirtual() && !ME->hasQualifier() && 120*27da15baSAnders Carlsson !canDevirtualizeMemberFunctionCalls(ME->getBase())) { 121*27da15baSAnders Carlsson Callee = BuildVirtualCall(Destructor, Dtor_Complete, This, Ty); 122*27da15baSAnders Carlsson } else { 123*27da15baSAnders Carlsson Callee = CGM.GetAddrOfFunction(GlobalDecl(Destructor, Dtor_Complete), Ty); 124*27da15baSAnders Carlsson } 125*27da15baSAnders Carlsson } else if (MD->isVirtual() && !ME->hasQualifier() && 126*27da15baSAnders Carlsson !canDevirtualizeMemberFunctionCalls(ME->getBase())) { 127*27da15baSAnders Carlsson Callee = BuildVirtualCall(MD, This, Ty); 128*27da15baSAnders Carlsson } else { 129*27da15baSAnders Carlsson Callee = CGM.GetAddrOfFunction(MD, Ty); 130*27da15baSAnders Carlsson } 131*27da15baSAnders Carlsson 132*27da15baSAnders Carlsson return EmitCXXMemberCall(MD, Callee, ReturnValue, This, 133*27da15baSAnders Carlsson CE->arg_begin(), CE->arg_end()); 134*27da15baSAnders Carlsson } 135*27da15baSAnders Carlsson 136*27da15baSAnders Carlsson RValue 137*27da15baSAnders Carlsson CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, 138*27da15baSAnders Carlsson ReturnValueSlot ReturnValue) { 139*27da15baSAnders Carlsson const BinaryOperator *BO = 140*27da15baSAnders Carlsson cast<BinaryOperator>(E->getCallee()->IgnoreParens()); 141*27da15baSAnders Carlsson const Expr *BaseExpr = BO->getLHS(); 142*27da15baSAnders Carlsson const Expr *MemFnExpr = BO->getRHS(); 143*27da15baSAnders Carlsson 144*27da15baSAnders Carlsson const MemberPointerType *MPT = 145*27da15baSAnders Carlsson MemFnExpr->getType()->getAs<MemberPointerType>(); 146*27da15baSAnders Carlsson const FunctionProtoType *FPT = 147*27da15baSAnders Carlsson MPT->getPointeeType()->getAs<FunctionProtoType>(); 148*27da15baSAnders Carlsson const CXXRecordDecl *RD = 149*27da15baSAnders Carlsson cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl()); 150*27da15baSAnders Carlsson 151*27da15baSAnders Carlsson const llvm::FunctionType *FTy = 152*27da15baSAnders Carlsson CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(RD, FPT), 153*27da15baSAnders Carlsson FPT->isVariadic()); 154*27da15baSAnders Carlsson 155*27da15baSAnders Carlsson const llvm::Type *Int8PtrTy = 156*27da15baSAnders Carlsson llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 157*27da15baSAnders Carlsson 158*27da15baSAnders Carlsson // Get the member function pointer. 159*27da15baSAnders Carlsson llvm::Value *MemFnPtr = 160*27da15baSAnders Carlsson CreateTempAlloca(ConvertType(MemFnExpr->getType()), "mem.fn"); 161*27da15baSAnders Carlsson EmitAggExpr(MemFnExpr, MemFnPtr, /*VolatileDest=*/false); 162*27da15baSAnders Carlsson 163*27da15baSAnders Carlsson // Emit the 'this' pointer. 164*27da15baSAnders Carlsson llvm::Value *This; 165*27da15baSAnders Carlsson 166*27da15baSAnders Carlsson if (BO->getOpcode() == BinaryOperator::PtrMemI) 167*27da15baSAnders Carlsson This = EmitScalarExpr(BaseExpr); 168*27da15baSAnders Carlsson else 169*27da15baSAnders Carlsson This = EmitLValue(BaseExpr).getAddress(); 170*27da15baSAnders Carlsson 171*27da15baSAnders Carlsson // Adjust it. 172*27da15baSAnders Carlsson llvm::Value *Adj = Builder.CreateStructGEP(MemFnPtr, 1); 173*27da15baSAnders Carlsson Adj = Builder.CreateLoad(Adj, "mem.fn.adj"); 174*27da15baSAnders Carlsson 175*27da15baSAnders Carlsson llvm::Value *Ptr = Builder.CreateBitCast(This, Int8PtrTy, "ptr"); 176*27da15baSAnders Carlsson Ptr = Builder.CreateGEP(Ptr, Adj, "adj"); 177*27da15baSAnders Carlsson 178*27da15baSAnders Carlsson This = Builder.CreateBitCast(Ptr, This->getType(), "this"); 179*27da15baSAnders Carlsson 180*27da15baSAnders Carlsson llvm::Value *FnPtr = Builder.CreateStructGEP(MemFnPtr, 0, "mem.fn.ptr"); 181*27da15baSAnders Carlsson 182*27da15baSAnders Carlsson const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); 183*27da15baSAnders Carlsson 184*27da15baSAnders Carlsson llvm::Value *FnAsInt = Builder.CreateLoad(FnPtr, "fn"); 185*27da15baSAnders Carlsson 186*27da15baSAnders Carlsson // If the LSB in the function pointer is 1, the function pointer points to 187*27da15baSAnders Carlsson // a virtual function. 188*27da15baSAnders Carlsson llvm::Value *IsVirtual 189*27da15baSAnders Carlsson = Builder.CreateAnd(FnAsInt, llvm::ConstantInt::get(PtrDiffTy, 1), 190*27da15baSAnders Carlsson "and"); 191*27da15baSAnders Carlsson 192*27da15baSAnders Carlsson IsVirtual = Builder.CreateTrunc(IsVirtual, 193*27da15baSAnders Carlsson llvm::Type::getInt1Ty(VMContext)); 194*27da15baSAnders Carlsson 195*27da15baSAnders Carlsson llvm::BasicBlock *FnVirtual = createBasicBlock("fn.virtual"); 196*27da15baSAnders Carlsson llvm::BasicBlock *FnNonVirtual = createBasicBlock("fn.nonvirtual"); 197*27da15baSAnders Carlsson llvm::BasicBlock *FnEnd = createBasicBlock("fn.end"); 198*27da15baSAnders Carlsson 199*27da15baSAnders Carlsson Builder.CreateCondBr(IsVirtual, FnVirtual, FnNonVirtual); 200*27da15baSAnders Carlsson EmitBlock(FnVirtual); 201*27da15baSAnders Carlsson 202*27da15baSAnders Carlsson const llvm::Type *VTableTy = 203*27da15baSAnders Carlsson FTy->getPointerTo()->getPointerTo()->getPointerTo(); 204*27da15baSAnders Carlsson 205*27da15baSAnders Carlsson llvm::Value *VTable = Builder.CreateBitCast(This, VTableTy); 206*27da15baSAnders Carlsson VTable = Builder.CreateLoad(VTable); 207*27da15baSAnders Carlsson 208*27da15baSAnders Carlsson VTable = Builder.CreateGEP(VTable, FnAsInt, "fn"); 209*27da15baSAnders Carlsson 210*27da15baSAnders Carlsson // Since the function pointer is 1 plus the virtual table offset, we 211*27da15baSAnders Carlsson // subtract 1 by using a GEP. 212*27da15baSAnders Carlsson VTable = Builder.CreateConstGEP1_64(VTable, (uint64_t)-1); 213*27da15baSAnders Carlsson 214*27da15baSAnders Carlsson llvm::Value *VirtualFn = Builder.CreateLoad(VTable, "virtualfn"); 215*27da15baSAnders Carlsson 216*27da15baSAnders Carlsson EmitBranch(FnEnd); 217*27da15baSAnders Carlsson EmitBlock(FnNonVirtual); 218*27da15baSAnders Carlsson 219*27da15baSAnders Carlsson // If the function is not virtual, just load the pointer. 220*27da15baSAnders Carlsson llvm::Value *NonVirtualFn = Builder.CreateLoad(FnPtr, "fn"); 221*27da15baSAnders Carlsson NonVirtualFn = Builder.CreateIntToPtr(NonVirtualFn, FTy->getPointerTo()); 222*27da15baSAnders Carlsson 223*27da15baSAnders Carlsson EmitBlock(FnEnd); 224*27da15baSAnders Carlsson 225*27da15baSAnders Carlsson llvm::PHINode *Callee = Builder.CreatePHI(FTy->getPointerTo()); 226*27da15baSAnders Carlsson Callee->reserveOperandSpace(2); 227*27da15baSAnders Carlsson Callee->addIncoming(VirtualFn, FnVirtual); 228*27da15baSAnders Carlsson Callee->addIncoming(NonVirtualFn, FnNonVirtual); 229*27da15baSAnders Carlsson 230*27da15baSAnders Carlsson CallArgList Args; 231*27da15baSAnders Carlsson 232*27da15baSAnders Carlsson QualType ThisType = 233*27da15baSAnders Carlsson getContext().getPointerType(getContext().getTagDeclType(RD)); 234*27da15baSAnders Carlsson 235*27da15baSAnders Carlsson // Push the this ptr. 236*27da15baSAnders Carlsson Args.push_back(std::make_pair(RValue::get(This), ThisType)); 237*27da15baSAnders Carlsson 238*27da15baSAnders Carlsson // And the rest of the call args 239*27da15baSAnders Carlsson EmitCallArgs(Args, FPT, E->arg_begin(), E->arg_end()); 240*27da15baSAnders Carlsson QualType ResultType = BO->getType()->getAs<FunctionType>()->getResultType(); 241*27da15baSAnders Carlsson return EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, 242*27da15baSAnders Carlsson ReturnValue, Args); 243*27da15baSAnders Carlsson } 244*27da15baSAnders Carlsson 245*27da15baSAnders Carlsson RValue 246*27da15baSAnders Carlsson CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, 247*27da15baSAnders Carlsson const CXXMethodDecl *MD, 248*27da15baSAnders Carlsson ReturnValueSlot ReturnValue) { 249*27da15baSAnders Carlsson assert(MD->isInstance() && 250*27da15baSAnders Carlsson "Trying to emit a member call expr on a static method!"); 251*27da15baSAnders Carlsson 252*27da15baSAnders Carlsson if (MD->isCopyAssignment()) { 253*27da15baSAnders Carlsson const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MD->getDeclContext()); 254*27da15baSAnders Carlsson if (ClassDecl->hasTrivialCopyAssignment()) { 255*27da15baSAnders Carlsson assert(!ClassDecl->hasUserDeclaredCopyAssignment() && 256*27da15baSAnders Carlsson "EmitCXXOperatorMemberCallExpr - user declared copy assignment"); 257*27da15baSAnders Carlsson llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 258*27da15baSAnders Carlsson llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress(); 259*27da15baSAnders Carlsson QualType Ty = E->getType(); 260*27da15baSAnders Carlsson EmitAggregateCopy(This, Src, Ty); 261*27da15baSAnders Carlsson return RValue::get(This); 262*27da15baSAnders Carlsson } 263*27da15baSAnders Carlsson } 264*27da15baSAnders Carlsson 265*27da15baSAnders Carlsson const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); 266*27da15baSAnders Carlsson const llvm::Type *Ty = 267*27da15baSAnders Carlsson CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(MD), 268*27da15baSAnders Carlsson FPT->isVariadic()); 269*27da15baSAnders Carlsson 270*27da15baSAnders Carlsson llvm::Value *This = EmitLValue(E->getArg(0)).getAddress(); 271*27da15baSAnders Carlsson 272*27da15baSAnders Carlsson llvm::Value *Callee; 273*27da15baSAnders Carlsson if (MD->isVirtual() && !canDevirtualizeMemberFunctionCalls(E->getArg(0))) 274*27da15baSAnders Carlsson Callee = BuildVirtualCall(MD, This, Ty); 275*27da15baSAnders Carlsson else 276*27da15baSAnders Carlsson Callee = CGM.GetAddrOfFunction(MD, Ty); 277*27da15baSAnders Carlsson 278*27da15baSAnders Carlsson return EmitCXXMemberCall(MD, Callee, ReturnValue, This, 279*27da15baSAnders Carlsson E->arg_begin() + 1, E->arg_end()); 280*27da15baSAnders Carlsson } 281*27da15baSAnders Carlsson 282*27da15baSAnders Carlsson void 283*27da15baSAnders Carlsson CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, 284*27da15baSAnders Carlsson const CXXConstructExpr *E) { 285*27da15baSAnders Carlsson assert(Dest && "Must have a destination!"); 286*27da15baSAnders Carlsson const CXXConstructorDecl *CD = E->getConstructor(); 287*27da15baSAnders Carlsson const ConstantArrayType *Array = 288*27da15baSAnders Carlsson getContext().getAsConstantArrayType(E->getType()); 289*27da15baSAnders Carlsson // For a copy constructor, even if it is trivial, must fall thru so 290*27da15baSAnders Carlsson // its argument is code-gen'ed. 291*27da15baSAnders Carlsson if (!CD->isCopyConstructor()) { 292*27da15baSAnders Carlsson QualType InitType = E->getType(); 293*27da15baSAnders Carlsson if (Array) 294*27da15baSAnders Carlsson InitType = getContext().getBaseElementType(Array); 295*27da15baSAnders Carlsson const CXXRecordDecl *RD = 296*27da15baSAnders Carlsson cast<CXXRecordDecl>(InitType->getAs<RecordType>()->getDecl()); 297*27da15baSAnders Carlsson if (RD->hasTrivialConstructor()) 298*27da15baSAnders Carlsson return; 299*27da15baSAnders Carlsson } 300*27da15baSAnders Carlsson // Code gen optimization to eliminate copy constructor and return 301*27da15baSAnders Carlsson // its first argument instead. 302*27da15baSAnders Carlsson if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { 303*27da15baSAnders Carlsson const Expr *Arg = E->getArg(0); 304*27da15baSAnders Carlsson 305*27da15baSAnders Carlsson if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { 306*27da15baSAnders Carlsson assert((ICE->getCastKind() == CastExpr::CK_NoOp || 307*27da15baSAnders Carlsson ICE->getCastKind() == CastExpr::CK_ConstructorConversion || 308*27da15baSAnders Carlsson ICE->getCastKind() == CastExpr::CK_UserDefinedConversion) && 309*27da15baSAnders Carlsson "Unknown implicit cast kind in constructor elision"); 310*27da15baSAnders Carlsson Arg = ICE->getSubExpr(); 311*27da15baSAnders Carlsson } 312*27da15baSAnders Carlsson 313*27da15baSAnders Carlsson if (const CXXFunctionalCastExpr *FCE = dyn_cast<CXXFunctionalCastExpr>(Arg)) 314*27da15baSAnders Carlsson Arg = FCE->getSubExpr(); 315*27da15baSAnders Carlsson 316*27da15baSAnders Carlsson if (const CXXBindTemporaryExpr *BindExpr = 317*27da15baSAnders Carlsson dyn_cast<CXXBindTemporaryExpr>(Arg)) 318*27da15baSAnders Carlsson Arg = BindExpr->getSubExpr(); 319*27da15baSAnders Carlsson 320*27da15baSAnders Carlsson EmitAggExpr(Arg, Dest, false); 321*27da15baSAnders Carlsson return; 322*27da15baSAnders Carlsson } 323*27da15baSAnders Carlsson if (Array) { 324*27da15baSAnders Carlsson QualType BaseElementTy = getContext().getBaseElementType(Array); 325*27da15baSAnders Carlsson const llvm::Type *BasePtr = ConvertType(BaseElementTy); 326*27da15baSAnders Carlsson BasePtr = llvm::PointerType::getUnqual(BasePtr); 327*27da15baSAnders Carlsson llvm::Value *BaseAddrPtr = 328*27da15baSAnders Carlsson Builder.CreateBitCast(Dest, BasePtr); 329*27da15baSAnders Carlsson 330*27da15baSAnders Carlsson EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, 331*27da15baSAnders Carlsson E->arg_begin(), E->arg_end()); 332*27da15baSAnders Carlsson } 333*27da15baSAnders Carlsson else 334*27da15baSAnders Carlsson // Call the constructor. 335*27da15baSAnders Carlsson EmitCXXConstructorCall(CD, Ctor_Complete, Dest, 336*27da15baSAnders Carlsson E->arg_begin(), E->arg_end()); 337*27da15baSAnders Carlsson } 338*27da15baSAnders Carlsson 33921122cf6SAnders Carlsson static uint64_t CalculateCookiePadding(ASTContext &Ctx, QualType ElementType) { 34021122cf6SAnders Carlsson const RecordType *RT = ElementType->getAs<RecordType>(); 34159486a2dSAnders Carlsson if (!RT) 34259486a2dSAnders Carlsson return 0; 34359486a2dSAnders Carlsson 34459486a2dSAnders Carlsson const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); 34559486a2dSAnders Carlsson if (!RD) 34659486a2dSAnders Carlsson return 0; 34759486a2dSAnders Carlsson 34859486a2dSAnders Carlsson // Check if the class has a trivial destructor. 34959486a2dSAnders Carlsson if (RD->hasTrivialDestructor()) { 35021122cf6SAnders Carlsson // Check if the usual deallocation function takes two arguments. 351adbe4249SAnders Carlsson const CXXMethodDecl *UsualDeallocationFunction = 0; 352adbe4249SAnders Carlsson 35321122cf6SAnders Carlsson DeclarationName OpName = 35421122cf6SAnders Carlsson Ctx.DeclarationNames.getCXXOperatorName(OO_Array_Delete); 35521122cf6SAnders Carlsson DeclContext::lookup_const_iterator Op, OpEnd; 35621122cf6SAnders Carlsson for (llvm::tie(Op, OpEnd) = RD->lookup(OpName); 35721122cf6SAnders Carlsson Op != OpEnd; ++Op) { 358adbe4249SAnders Carlsson const CXXMethodDecl *Delete = cast<CXXMethodDecl>(*Op); 35921122cf6SAnders Carlsson 36021122cf6SAnders Carlsson if (Delete->isUsualDeallocationFunction()) { 361adbe4249SAnders Carlsson UsualDeallocationFunction = Delete; 36221122cf6SAnders Carlsson break; 36321122cf6SAnders Carlsson } 36421122cf6SAnders Carlsson } 365adbe4249SAnders Carlsson 366adbe4249SAnders Carlsson // No usual deallocation function, we don't need a cookie. 367adbe4249SAnders Carlsson if (!UsualDeallocationFunction) 368adbe4249SAnders Carlsson return 0; 369adbe4249SAnders Carlsson 370adbe4249SAnders Carlsson // The usual deallocation function doesn't take a size_t argument, so we 371adbe4249SAnders Carlsson // don't need a cookie. 372adbe4249SAnders Carlsson if (UsualDeallocationFunction->getNumParams() == 1) 373adbe4249SAnders Carlsson return 0; 374adbe4249SAnders Carlsson 375adbe4249SAnders Carlsson assert(UsualDeallocationFunction->getNumParams() == 2 && 376adbe4249SAnders Carlsson "Unexpected deallocation function type!"); 37759486a2dSAnders Carlsson } 37859486a2dSAnders Carlsson 37921122cf6SAnders Carlsson // Padding is the maximum of sizeof(size_t) and alignof(ElementType) 38059486a2dSAnders Carlsson return std::max(Ctx.getTypeSize(Ctx.getSizeType()), 38121122cf6SAnders Carlsson static_cast<uint64_t>(Ctx.getTypeAlign(ElementType))) / 8; 38221122cf6SAnders Carlsson } 38321122cf6SAnders Carlsson 38421122cf6SAnders Carlsson static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) { 38521122cf6SAnders Carlsson if (!E->isArray()) 38621122cf6SAnders Carlsson return 0; 38721122cf6SAnders Carlsson 388399f499fSAnders Carlsson // No cookie is required if the new operator being used is 389399f499fSAnders Carlsson // ::operator new[](size_t, void*). 390399f499fSAnders Carlsson const FunctionDecl *OperatorNew = E->getOperatorNew(); 391399f499fSAnders Carlsson if (OperatorNew->getDeclContext()->getLookupContext()->isFileContext()) { 392399f499fSAnders Carlsson if (OperatorNew->getNumParams() == 2) { 393399f499fSAnders Carlsson CanQualType ParamType = 394399f499fSAnders Carlsson Ctx.getCanonicalType(OperatorNew->getParamDecl(1)->getType()); 395399f499fSAnders Carlsson 396399f499fSAnders Carlsson if (ParamType == Ctx.VoidPtrTy) 397399f499fSAnders Carlsson return 0; 398399f499fSAnders Carlsson } 399399f499fSAnders Carlsson } 400399f499fSAnders Carlsson 40121122cf6SAnders Carlsson return CalculateCookiePadding(Ctx, E->getAllocatedType()); 40259486a2dSAnders Carlsson } 40359486a2dSAnders Carlsson 40459486a2dSAnders Carlsson static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, 40559486a2dSAnders Carlsson const CXXNewExpr *E, 40659486a2dSAnders Carlsson llvm::Value *& NumElements) { 40759486a2dSAnders Carlsson QualType Type = E->getAllocatedType(); 40859486a2dSAnders Carlsson uint64_t TypeSizeInBytes = CGF.getContext().getTypeSize(Type) / 8; 40959486a2dSAnders Carlsson const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); 41059486a2dSAnders Carlsson 41159486a2dSAnders Carlsson if (!E->isArray()) 41259486a2dSAnders Carlsson return llvm::ConstantInt::get(SizeTy, TypeSizeInBytes); 41359486a2dSAnders Carlsson 41459486a2dSAnders Carlsson uint64_t CookiePadding = CalculateCookiePadding(CGF.getContext(), E); 41559486a2dSAnders Carlsson 41659486a2dSAnders Carlsson Expr::EvalResult Result; 41759486a2dSAnders Carlsson if (E->getArraySize()->Evaluate(Result, CGF.getContext()) && 41859486a2dSAnders Carlsson !Result.HasSideEffects && Result.Val.isInt()) { 41959486a2dSAnders Carlsson 42059486a2dSAnders Carlsson uint64_t AllocSize = 42159486a2dSAnders Carlsson Result.Val.getInt().getZExtValue() * TypeSizeInBytes + CookiePadding; 42259486a2dSAnders Carlsson 42359486a2dSAnders Carlsson NumElements = 42459486a2dSAnders Carlsson llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue()); 42559486a2dSAnders Carlsson 42659486a2dSAnders Carlsson return llvm::ConstantInt::get(SizeTy, AllocSize); 42759486a2dSAnders Carlsson } 42859486a2dSAnders Carlsson 42959486a2dSAnders Carlsson // Emit the array size expression. 43059486a2dSAnders Carlsson NumElements = CGF.EmitScalarExpr(E->getArraySize()); 43159486a2dSAnders Carlsson 43259486a2dSAnders Carlsson // Multiply with the type size. 43359486a2dSAnders Carlsson llvm::Value *V = 43459486a2dSAnders Carlsson CGF.Builder.CreateMul(NumElements, 43559486a2dSAnders Carlsson llvm::ConstantInt::get(SizeTy, TypeSizeInBytes)); 43659486a2dSAnders Carlsson 43759486a2dSAnders Carlsson // And add the cookie padding if necessary. 43859486a2dSAnders Carlsson if (CookiePadding) 43959486a2dSAnders Carlsson V = CGF.Builder.CreateAdd(V, llvm::ConstantInt::get(SizeTy, CookiePadding)); 44059486a2dSAnders Carlsson 44159486a2dSAnders Carlsson return V; 44259486a2dSAnders Carlsson } 44359486a2dSAnders Carlsson 44459486a2dSAnders Carlsson static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, 44559486a2dSAnders Carlsson llvm::Value *NewPtr, 44659486a2dSAnders Carlsson llvm::Value *NumElements) { 4473a202f60SAnders Carlsson if (E->isArray()) { 4483a202f60SAnders Carlsson if (CXXConstructorDecl *Ctor = E->getConstructor()) 4493a202f60SAnders Carlsson CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr, 4503a202f60SAnders Carlsson E->constructor_arg_begin(), 4513a202f60SAnders Carlsson E->constructor_arg_end()); 4523a202f60SAnders Carlsson return; 4533a202f60SAnders Carlsson } 4543a202f60SAnders Carlsson 45559486a2dSAnders Carlsson QualType AllocType = E->getAllocatedType(); 45659486a2dSAnders Carlsson 45759486a2dSAnders Carlsson if (CXXConstructorDecl *Ctor = E->getConstructor()) { 45859486a2dSAnders Carlsson CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, 45959486a2dSAnders Carlsson E->constructor_arg_begin(), 46059486a2dSAnders Carlsson E->constructor_arg_end()); 46159486a2dSAnders Carlsson 46259486a2dSAnders Carlsson return; 46359486a2dSAnders Carlsson } 46459486a2dSAnders Carlsson 46559486a2dSAnders Carlsson // We have a POD type. 46659486a2dSAnders Carlsson if (E->getNumConstructorArgs() == 0) 46759486a2dSAnders Carlsson return; 46859486a2dSAnders Carlsson 46959486a2dSAnders Carlsson assert(E->getNumConstructorArgs() == 1 && 47059486a2dSAnders Carlsson "Can only have one argument to initializer of POD type."); 47159486a2dSAnders Carlsson 47259486a2dSAnders Carlsson const Expr *Init = E->getConstructorArg(0); 47359486a2dSAnders Carlsson 47459486a2dSAnders Carlsson if (!CGF.hasAggregateLLVMType(AllocType)) 47559486a2dSAnders Carlsson CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr, 47659486a2dSAnders Carlsson AllocType.isVolatileQualified(), AllocType); 47759486a2dSAnders Carlsson else if (AllocType->isAnyComplexType()) 47859486a2dSAnders Carlsson CGF.EmitComplexExprIntoAddr(Init, NewPtr, 47959486a2dSAnders Carlsson AllocType.isVolatileQualified()); 48059486a2dSAnders Carlsson else 48159486a2dSAnders Carlsson CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); 48259486a2dSAnders Carlsson } 48359486a2dSAnders Carlsson 48459486a2dSAnders Carlsson llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { 48559486a2dSAnders Carlsson QualType AllocType = E->getAllocatedType(); 48659486a2dSAnders Carlsson FunctionDecl *NewFD = E->getOperatorNew(); 48759486a2dSAnders Carlsson const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>(); 48859486a2dSAnders Carlsson 48959486a2dSAnders Carlsson CallArgList NewArgs; 49059486a2dSAnders Carlsson 49159486a2dSAnders Carlsson // The allocation size is the first argument. 49259486a2dSAnders Carlsson QualType SizeTy = getContext().getSizeType(); 49359486a2dSAnders Carlsson 49459486a2dSAnders Carlsson llvm::Value *NumElements = 0; 49559486a2dSAnders Carlsson llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements); 49659486a2dSAnders Carlsson 49759486a2dSAnders Carlsson NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); 49859486a2dSAnders Carlsson 49959486a2dSAnders Carlsson // Emit the rest of the arguments. 50059486a2dSAnders Carlsson // FIXME: Ideally, this should just use EmitCallArgs. 50159486a2dSAnders Carlsson CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); 50259486a2dSAnders Carlsson 50359486a2dSAnders Carlsson // First, use the types from the function type. 50459486a2dSAnders Carlsson // We start at 1 here because the first argument (the allocation size) 50559486a2dSAnders Carlsson // has already been emitted. 50659486a2dSAnders Carlsson for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { 50759486a2dSAnders Carlsson QualType ArgType = NewFTy->getArgType(i); 50859486a2dSAnders Carlsson 50959486a2dSAnders Carlsson assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). 51059486a2dSAnders Carlsson getTypePtr() == 51159486a2dSAnders Carlsson getContext().getCanonicalType(NewArg->getType()).getTypePtr() && 51259486a2dSAnders Carlsson "type mismatch in call argument!"); 51359486a2dSAnders Carlsson 51459486a2dSAnders Carlsson NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 51559486a2dSAnders Carlsson ArgType)); 51659486a2dSAnders Carlsson 51759486a2dSAnders Carlsson } 51859486a2dSAnders Carlsson 51959486a2dSAnders Carlsson // Either we've emitted all the call args, or we have a call to a 52059486a2dSAnders Carlsson // variadic function. 52159486a2dSAnders Carlsson assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && 52259486a2dSAnders Carlsson "Extra arguments in non-variadic function!"); 52359486a2dSAnders Carlsson 52459486a2dSAnders Carlsson // If we still have any arguments, emit them using the type of the argument. 52559486a2dSAnders Carlsson for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); 52659486a2dSAnders Carlsson NewArg != NewArgEnd; ++NewArg) { 52759486a2dSAnders Carlsson QualType ArgType = NewArg->getType(); 52859486a2dSAnders Carlsson NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 52959486a2dSAnders Carlsson ArgType)); 53059486a2dSAnders Carlsson } 53159486a2dSAnders Carlsson 53259486a2dSAnders Carlsson // Emit the call to new. 53359486a2dSAnders Carlsson RValue RV = 53459486a2dSAnders Carlsson EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), 53561a401caSAnders Carlsson CGM.GetAddrOfFunction(NewFD), ReturnValueSlot(), NewArgs, NewFD); 53659486a2dSAnders Carlsson 53759486a2dSAnders Carlsson // If an allocation function is declared with an empty exception specification 53859486a2dSAnders Carlsson // it returns null to indicate failure to allocate storage. [expr.new]p13. 53959486a2dSAnders Carlsson // (We don't need to check for null when there's no new initializer and 54059486a2dSAnders Carlsson // we're allocating a POD type). 54159486a2dSAnders Carlsson bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && 54259486a2dSAnders Carlsson !(AllocType->isPODType() && !E->hasInitializer()); 54359486a2dSAnders Carlsson 54459486a2dSAnders Carlsson llvm::BasicBlock *NewNull = 0; 54559486a2dSAnders Carlsson llvm::BasicBlock *NewNotNull = 0; 54659486a2dSAnders Carlsson llvm::BasicBlock *NewEnd = 0; 54759486a2dSAnders Carlsson 54859486a2dSAnders Carlsson llvm::Value *NewPtr = RV.getScalarVal(); 54959486a2dSAnders Carlsson 55059486a2dSAnders Carlsson if (NullCheckResult) { 55159486a2dSAnders Carlsson NewNull = createBasicBlock("new.null"); 55259486a2dSAnders Carlsson NewNotNull = createBasicBlock("new.notnull"); 55359486a2dSAnders Carlsson NewEnd = createBasicBlock("new.end"); 55459486a2dSAnders Carlsson 55559486a2dSAnders Carlsson llvm::Value *IsNull = 55659486a2dSAnders Carlsson Builder.CreateICmpEQ(NewPtr, 55759486a2dSAnders Carlsson llvm::Constant::getNullValue(NewPtr->getType()), 55859486a2dSAnders Carlsson "isnull"); 55959486a2dSAnders Carlsson 56059486a2dSAnders Carlsson Builder.CreateCondBr(IsNull, NewNull, NewNotNull); 56159486a2dSAnders Carlsson EmitBlock(NewNotNull); 56259486a2dSAnders Carlsson } 56359486a2dSAnders Carlsson 56459486a2dSAnders Carlsson if (uint64_t CookiePadding = CalculateCookiePadding(getContext(), E)) { 56559486a2dSAnders Carlsson uint64_t CookieOffset = 56659486a2dSAnders Carlsson CookiePadding - getContext().getTypeSize(SizeTy) / 8; 56759486a2dSAnders Carlsson 56859486a2dSAnders Carlsson llvm::Value *NumElementsPtr = 56959486a2dSAnders Carlsson Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset); 57059486a2dSAnders Carlsson 57159486a2dSAnders Carlsson NumElementsPtr = Builder.CreateBitCast(NumElementsPtr, 57259486a2dSAnders Carlsson ConvertType(SizeTy)->getPointerTo()); 57359486a2dSAnders Carlsson Builder.CreateStore(NumElements, NumElementsPtr); 57459486a2dSAnders Carlsson 57559486a2dSAnders Carlsson // Now add the padding to the new ptr. 57659486a2dSAnders Carlsson NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr, CookiePadding); 57759486a2dSAnders Carlsson } 57859486a2dSAnders Carlsson 57959486a2dSAnders Carlsson NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); 58059486a2dSAnders Carlsson 58159486a2dSAnders Carlsson EmitNewInitializer(*this, E, NewPtr, NumElements); 58259486a2dSAnders Carlsson 58359486a2dSAnders Carlsson if (NullCheckResult) { 58459486a2dSAnders Carlsson Builder.CreateBr(NewEnd); 58559486a2dSAnders Carlsson NewNotNull = Builder.GetInsertBlock(); 58659486a2dSAnders Carlsson EmitBlock(NewNull); 58759486a2dSAnders Carlsson Builder.CreateBr(NewEnd); 58859486a2dSAnders Carlsson EmitBlock(NewEnd); 58959486a2dSAnders Carlsson 59059486a2dSAnders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); 59159486a2dSAnders Carlsson PHI->reserveOperandSpace(2); 59259486a2dSAnders Carlsson PHI->addIncoming(NewPtr, NewNotNull); 59359486a2dSAnders Carlsson PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull); 59459486a2dSAnders Carlsson 59559486a2dSAnders Carlsson NewPtr = PHI; 59659486a2dSAnders Carlsson } 59759486a2dSAnders Carlsson 59859486a2dSAnders Carlsson return NewPtr; 59959486a2dSAnders Carlsson } 60059486a2dSAnders Carlsson 60121122cf6SAnders Carlsson static std::pair<llvm::Value *, llvm::Value *> 60221122cf6SAnders Carlsson GetAllocatedObjectPtrAndNumElements(CodeGenFunction &CGF, 60321122cf6SAnders Carlsson llvm::Value *Ptr, QualType DeleteTy) { 60421122cf6SAnders Carlsson QualType SizeTy = CGF.getContext().getSizeType(); 60521122cf6SAnders Carlsson const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy); 60621122cf6SAnders Carlsson 60721122cf6SAnders Carlsson uint64_t DeleteTypeAlign = CGF.getContext().getTypeAlign(DeleteTy); 60821122cf6SAnders Carlsson uint64_t CookiePadding = std::max(CGF.getContext().getTypeSize(SizeTy), 60921122cf6SAnders Carlsson DeleteTypeAlign) / 8; 61021122cf6SAnders Carlsson assert(CookiePadding && "CookiePadding should not be 0."); 61121122cf6SAnders Carlsson 61221122cf6SAnders Carlsson const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 61321122cf6SAnders Carlsson uint64_t CookieOffset = 61421122cf6SAnders Carlsson CookiePadding - CGF.getContext().getTypeSize(SizeTy) / 8; 61521122cf6SAnders Carlsson 61621122cf6SAnders Carlsson llvm::Value *AllocatedObjectPtr = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy); 61721122cf6SAnders Carlsson AllocatedObjectPtr = 61821122cf6SAnders Carlsson CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr, 61921122cf6SAnders Carlsson -CookiePadding); 62021122cf6SAnders Carlsson 62121122cf6SAnders Carlsson llvm::Value *NumElementsPtr = 62221122cf6SAnders Carlsson CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr, 62321122cf6SAnders Carlsson CookieOffset); 62421122cf6SAnders Carlsson NumElementsPtr = 62521122cf6SAnders Carlsson CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo()); 62621122cf6SAnders Carlsson 62721122cf6SAnders Carlsson llvm::Value *NumElements = CGF.Builder.CreateLoad(NumElementsPtr); 62821122cf6SAnders Carlsson NumElements = 62921122cf6SAnders Carlsson CGF.Builder.CreateIntCast(NumElements, SizeLTy, /*isSigned=*/false); 63021122cf6SAnders Carlsson 63121122cf6SAnders Carlsson return std::make_pair(AllocatedObjectPtr, NumElements); 63221122cf6SAnders Carlsson } 63321122cf6SAnders Carlsson 63459486a2dSAnders Carlsson void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, 63559486a2dSAnders Carlsson llvm::Value *Ptr, 63659486a2dSAnders Carlsson QualType DeleteTy) { 63759486a2dSAnders Carlsson const FunctionProtoType *DeleteFTy = 63859486a2dSAnders Carlsson DeleteFD->getType()->getAs<FunctionProtoType>(); 63959486a2dSAnders Carlsson 64059486a2dSAnders Carlsson CallArgList DeleteArgs; 64159486a2dSAnders Carlsson 64221122cf6SAnders Carlsson // Check if we need to pass the size to the delete operator. 64321122cf6SAnders Carlsson llvm::Value *Size = 0; 64421122cf6SAnders Carlsson QualType SizeTy; 64521122cf6SAnders Carlsson if (DeleteFTy->getNumArgs() == 2) { 64621122cf6SAnders Carlsson SizeTy = DeleteFTy->getArgType(1); 64721122cf6SAnders Carlsson uint64_t DeleteTypeSize = getContext().getTypeSize(DeleteTy) / 8; 64821122cf6SAnders Carlsson Size = llvm::ConstantInt::get(ConvertType(SizeTy), DeleteTypeSize); 64921122cf6SAnders Carlsson } 65021122cf6SAnders Carlsson 65121122cf6SAnders Carlsson if (DeleteFD->getOverloadedOperator() == OO_Array_Delete && 65221122cf6SAnders Carlsson 65321122cf6SAnders Carlsson CalculateCookiePadding(getContext(), DeleteTy)) { 65421122cf6SAnders Carlsson // We need to get the number of elements in the array from the cookie. 65521122cf6SAnders Carlsson llvm::Value *AllocatedObjectPtr; 65621122cf6SAnders Carlsson llvm::Value *NumElements; 65721122cf6SAnders Carlsson llvm::tie(AllocatedObjectPtr, NumElements) = 65821122cf6SAnders Carlsson GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy); 65921122cf6SAnders Carlsson 66021122cf6SAnders Carlsson // Multiply the size with the number of elements. 66121122cf6SAnders Carlsson if (Size) 66221122cf6SAnders Carlsson Size = Builder.CreateMul(NumElements, Size); 66321122cf6SAnders Carlsson 66421122cf6SAnders Carlsson Ptr = AllocatedObjectPtr; 66521122cf6SAnders Carlsson } 66621122cf6SAnders Carlsson 66759486a2dSAnders Carlsson QualType ArgTy = DeleteFTy->getArgType(0); 66859486a2dSAnders Carlsson llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); 66959486a2dSAnders Carlsson DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); 67059486a2dSAnders Carlsson 67121122cf6SAnders Carlsson if (Size) 67259486a2dSAnders Carlsson DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy)); 67359486a2dSAnders Carlsson 67459486a2dSAnders Carlsson // Emit the call to delete. 67559486a2dSAnders Carlsson EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), 67659486a2dSAnders Carlsson DeleteArgs), 67761a401caSAnders Carlsson CGM.GetAddrOfFunction(DeleteFD), ReturnValueSlot(), 67859486a2dSAnders Carlsson DeleteArgs, DeleteFD); 67959486a2dSAnders Carlsson } 68059486a2dSAnders Carlsson 68159486a2dSAnders Carlsson void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { 68259486a2dSAnders Carlsson 68359486a2dSAnders Carlsson // Get at the argument before we performed the implicit conversion 68459486a2dSAnders Carlsson // to void*. 68559486a2dSAnders Carlsson const Expr *Arg = E->getArgument(); 68659486a2dSAnders Carlsson while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { 68759486a2dSAnders Carlsson if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion && 68859486a2dSAnders Carlsson ICE->getType()->isVoidPointerType()) 68959486a2dSAnders Carlsson Arg = ICE->getSubExpr(); 69059486a2dSAnders Carlsson else 69159486a2dSAnders Carlsson break; 69259486a2dSAnders Carlsson } 69359486a2dSAnders Carlsson 69459486a2dSAnders Carlsson QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType(); 69559486a2dSAnders Carlsson 69659486a2dSAnders Carlsson llvm::Value *Ptr = EmitScalarExpr(Arg); 69759486a2dSAnders Carlsson 69859486a2dSAnders Carlsson // Null check the pointer. 69959486a2dSAnders Carlsson llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); 70059486a2dSAnders Carlsson llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); 70159486a2dSAnders Carlsson 70259486a2dSAnders Carlsson llvm::Value *IsNull = 70359486a2dSAnders Carlsson Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()), 70459486a2dSAnders Carlsson "isnull"); 70559486a2dSAnders Carlsson 70659486a2dSAnders Carlsson Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); 70759486a2dSAnders Carlsson EmitBlock(DeleteNotNull); 70859486a2dSAnders Carlsson 70959486a2dSAnders Carlsson bool ShouldCallDelete = true; 71059486a2dSAnders Carlsson 71159486a2dSAnders Carlsson // Call the destructor if necessary. 71259486a2dSAnders Carlsson if (const RecordType *RT = DeleteTy->getAs<RecordType>()) { 71359486a2dSAnders Carlsson if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { 71459486a2dSAnders Carlsson if (!RD->hasTrivialDestructor()) { 71559486a2dSAnders Carlsson const CXXDestructorDecl *Dtor = RD->getDestructor(getContext()); 71659486a2dSAnders Carlsson if (E->isArrayForm()) { 71721122cf6SAnders Carlsson llvm::Value *AllocatedObjectPtr; 71821122cf6SAnders Carlsson llvm::Value *NumElements; 71921122cf6SAnders Carlsson llvm::tie(AllocatedObjectPtr, NumElements) = 72021122cf6SAnders Carlsson GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy); 721f5af8deaSAnders Carlsson 72259486a2dSAnders Carlsson EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr); 723f5af8deaSAnders Carlsson } else if (Dtor->isVirtual()) { 72459486a2dSAnders Carlsson const llvm::Type *Ty = 72559486a2dSAnders Carlsson CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor), 72659486a2dSAnders Carlsson /*isVariadic=*/false); 72759486a2dSAnders Carlsson 72859486a2dSAnders Carlsson llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty); 729bfb3671bSAnders Carlsson EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, 0, 0); 73059486a2dSAnders Carlsson 73159486a2dSAnders Carlsson // The dtor took care of deleting the object. 73259486a2dSAnders Carlsson ShouldCallDelete = false; 73359486a2dSAnders Carlsson } else 73459486a2dSAnders Carlsson EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr); 73559486a2dSAnders Carlsson } 73659486a2dSAnders Carlsson } 73759486a2dSAnders Carlsson } 73859486a2dSAnders Carlsson 73959486a2dSAnders Carlsson if (ShouldCallDelete) 74059486a2dSAnders Carlsson EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy); 74159486a2dSAnders Carlsson 74259486a2dSAnders Carlsson EmitBlock(DeleteEnd); 74359486a2dSAnders Carlsson } 74459486a2dSAnders Carlsson 74559486a2dSAnders Carlsson llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { 74659486a2dSAnders Carlsson QualType Ty = E->getType(); 74759486a2dSAnders Carlsson const llvm::Type *LTy = ConvertType(Ty)->getPointerTo(); 748fd7dfeb7SAnders Carlsson 7493f4336cbSAnders Carlsson if (E->isTypeOperand()) { 7503f4336cbSAnders Carlsson llvm::Constant *TypeInfo = 7513f4336cbSAnders Carlsson CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand()); 7523f4336cbSAnders Carlsson return Builder.CreateBitCast(TypeInfo, LTy); 7533f4336cbSAnders Carlsson } 754fd7dfeb7SAnders Carlsson 75559486a2dSAnders Carlsson Expr *subE = E->getExprOperand(); 75659486a2dSAnders Carlsson Ty = subE->getType(); 75759486a2dSAnders Carlsson CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); 75859486a2dSAnders Carlsson Ty = CanTy.getUnqualifiedType().getNonReferenceType(); 75959486a2dSAnders Carlsson if (const RecordType *RT = Ty->getAs<RecordType>()) { 76059486a2dSAnders Carlsson const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 76159486a2dSAnders Carlsson if (RD->isPolymorphic()) { 76259486a2dSAnders Carlsson // FIXME: if subE is an lvalue do 76359486a2dSAnders Carlsson LValue Obj = EmitLValue(subE); 76459486a2dSAnders Carlsson llvm::Value *This = Obj.getAddress(); 76559486a2dSAnders Carlsson LTy = LTy->getPointerTo()->getPointerTo(); 76659486a2dSAnders Carlsson llvm::Value *V = Builder.CreateBitCast(This, LTy); 76759486a2dSAnders Carlsson // We need to do a zero check for *p, unless it has NonNullAttr. 76859486a2dSAnders Carlsson // FIXME: PointerType->hasAttr<NonNullAttr>() 76959486a2dSAnders Carlsson bool CanBeZero = false; 77059486a2dSAnders Carlsson if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens())) 77159486a2dSAnders Carlsson if (UO->getOpcode() == UnaryOperator::Deref) 77259486a2dSAnders Carlsson CanBeZero = true; 77359486a2dSAnders Carlsson if (CanBeZero) { 77459486a2dSAnders Carlsson llvm::BasicBlock *NonZeroBlock = createBasicBlock(); 77559486a2dSAnders Carlsson llvm::BasicBlock *ZeroBlock = createBasicBlock(); 77659486a2dSAnders Carlsson 77759486a2dSAnders Carlsson llvm::Value *Zero = llvm::Constant::getNullValue(LTy); 77859486a2dSAnders Carlsson Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), 77959486a2dSAnders Carlsson NonZeroBlock, ZeroBlock); 78059486a2dSAnders Carlsson EmitBlock(ZeroBlock); 78159486a2dSAnders Carlsson /// Call __cxa_bad_typeid 78259486a2dSAnders Carlsson const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); 78359486a2dSAnders Carlsson const llvm::FunctionType *FTy; 78459486a2dSAnders Carlsson FTy = llvm::FunctionType::get(ResultType, false); 78559486a2dSAnders Carlsson llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); 78659486a2dSAnders Carlsson Builder.CreateCall(F)->setDoesNotReturn(); 78759486a2dSAnders Carlsson Builder.CreateUnreachable(); 78859486a2dSAnders Carlsson EmitBlock(NonZeroBlock); 78959486a2dSAnders Carlsson } 79059486a2dSAnders Carlsson V = Builder.CreateLoad(V, "vtable"); 79159486a2dSAnders Carlsson V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); 79259486a2dSAnders Carlsson V = Builder.CreateLoad(V); 79359486a2dSAnders Carlsson return V; 79459486a2dSAnders Carlsson } 79559486a2dSAnders Carlsson } 7963f4336cbSAnders Carlsson return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(Ty), LTy); 79759486a2dSAnders Carlsson } 79859486a2dSAnders Carlsson 79959486a2dSAnders Carlsson llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, 80059486a2dSAnders Carlsson const CXXDynamicCastExpr *DCE) { 8013f4336cbSAnders Carlsson QualType SrcTy = DCE->getSubExpr()->getType(); 8023f4336cbSAnders Carlsson QualType DestTy = DCE->getTypeAsWritten(); 8033f4336cbSAnders Carlsson QualType InnerType = DestTy->getPointeeType(); 8043f4336cbSAnders Carlsson 80559486a2dSAnders Carlsson const llvm::Type *LTy = ConvertType(DCE->getType()); 80659486a2dSAnders Carlsson 80759486a2dSAnders Carlsson bool CanBeZero = false; 80859486a2dSAnders Carlsson bool ToVoid = false; 80959486a2dSAnders Carlsson bool ThrowOnBad = false; 8103f4336cbSAnders Carlsson if (DestTy->isPointerType()) { 81159486a2dSAnders Carlsson // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this 81259486a2dSAnders Carlsson CanBeZero = true; 81359486a2dSAnders Carlsson if (InnerType->isVoidType()) 81459486a2dSAnders Carlsson ToVoid = true; 81559486a2dSAnders Carlsson } else { 81659486a2dSAnders Carlsson LTy = LTy->getPointerTo(); 81759486a2dSAnders Carlsson ThrowOnBad = true; 81859486a2dSAnders Carlsson } 81959486a2dSAnders Carlsson 8203f4336cbSAnders Carlsson if (SrcTy->isPointerType() || SrcTy->isReferenceType()) 8213f4336cbSAnders Carlsson SrcTy = SrcTy->getPointeeType(); 8223f4336cbSAnders Carlsson SrcTy = SrcTy.getUnqualifiedType(); 8233f4336cbSAnders Carlsson 8240087bc85SAnders Carlsson if (DestTy->isPointerType() || DestTy->isReferenceType()) 8253f4336cbSAnders Carlsson DestTy = DestTy->getPointeeType(); 8263f4336cbSAnders Carlsson DestTy = DestTy.getUnqualifiedType(); 82759486a2dSAnders Carlsson 82859486a2dSAnders Carlsson llvm::BasicBlock *ContBlock = createBasicBlock(); 82959486a2dSAnders Carlsson llvm::BasicBlock *NullBlock = 0; 83059486a2dSAnders Carlsson llvm::BasicBlock *NonZeroBlock = 0; 83159486a2dSAnders Carlsson if (CanBeZero) { 83259486a2dSAnders Carlsson NonZeroBlock = createBasicBlock(); 83359486a2dSAnders Carlsson NullBlock = createBasicBlock(); 8343f4336cbSAnders Carlsson Builder.CreateCondBr(Builder.CreateIsNotNull(V), NonZeroBlock, NullBlock); 83559486a2dSAnders Carlsson EmitBlock(NonZeroBlock); 83659486a2dSAnders Carlsson } 83759486a2dSAnders Carlsson 83859486a2dSAnders Carlsson llvm::BasicBlock *BadCastBlock = 0; 83959486a2dSAnders Carlsson 8403f4336cbSAnders Carlsson const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType()); 84159486a2dSAnders Carlsson 84259486a2dSAnders Carlsson // See if this is a dynamic_cast(void*) 84359486a2dSAnders Carlsson if (ToVoid) { 84459486a2dSAnders Carlsson llvm::Value *This = V; 84559486a2dSAnders Carlsson V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo()); 84659486a2dSAnders Carlsson V = Builder.CreateLoad(V, "vtable"); 84759486a2dSAnders Carlsson V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL); 84859486a2dSAnders Carlsson V = Builder.CreateLoad(V, "offset to top"); 84959486a2dSAnders Carlsson This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext)); 85059486a2dSAnders Carlsson V = Builder.CreateInBoundsGEP(This, V); 85159486a2dSAnders Carlsson V = Builder.CreateBitCast(V, LTy); 85259486a2dSAnders Carlsson } else { 85359486a2dSAnders Carlsson /// Call __dynamic_cast 85459486a2dSAnders Carlsson const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext); 85559486a2dSAnders Carlsson const llvm::FunctionType *FTy; 85659486a2dSAnders Carlsson std::vector<const llvm::Type*> ArgTys; 85759486a2dSAnders Carlsson const llvm::Type *PtrToInt8Ty 85859486a2dSAnders Carlsson = llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 85959486a2dSAnders Carlsson ArgTys.push_back(PtrToInt8Ty); 86059486a2dSAnders Carlsson ArgTys.push_back(PtrToInt8Ty); 86159486a2dSAnders Carlsson ArgTys.push_back(PtrToInt8Ty); 86259486a2dSAnders Carlsson ArgTys.push_back(PtrDiffTy); 86359486a2dSAnders Carlsson FTy = llvm::FunctionType::get(ResultType, ArgTys, false); 86459486a2dSAnders Carlsson 86559486a2dSAnders Carlsson // FIXME: Calculate better hint. 86659486a2dSAnders Carlsson llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL); 8673f4336cbSAnders Carlsson 8683f4336cbSAnders Carlsson assert(SrcTy->isRecordType() && "Src type must be record type!"); 8693f4336cbSAnders Carlsson assert(DestTy->isRecordType() && "Dest type must be record type!"); 8703f4336cbSAnders Carlsson 871247894b3SDouglas Gregor llvm::Value *SrcArg 872247894b3SDouglas Gregor = CGM.GetAddrOfRTTIDescriptor(SrcTy.getUnqualifiedType()); 873247894b3SDouglas Gregor llvm::Value *DestArg 874247894b3SDouglas Gregor = CGM.GetAddrOfRTTIDescriptor(DestTy.getUnqualifiedType()); 8753f4336cbSAnders Carlsson 87659486a2dSAnders Carlsson V = Builder.CreateBitCast(V, PtrToInt8Ty); 87759486a2dSAnders Carlsson V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"), 8783f4336cbSAnders Carlsson V, SrcArg, DestArg, hint); 87959486a2dSAnders Carlsson V = Builder.CreateBitCast(V, LTy); 88059486a2dSAnders Carlsson 88159486a2dSAnders Carlsson if (ThrowOnBad) { 88259486a2dSAnders Carlsson BadCastBlock = createBasicBlock(); 88359486a2dSAnders Carlsson 8843f4336cbSAnders Carlsson Builder.CreateCondBr(Builder.CreateIsNotNull(V), ContBlock, BadCastBlock); 88559486a2dSAnders Carlsson EmitBlock(BadCastBlock); 88659486a2dSAnders Carlsson /// Call __cxa_bad_cast 88759486a2dSAnders Carlsson ResultType = llvm::Type::getVoidTy(VMContext); 88859486a2dSAnders Carlsson const llvm::FunctionType *FBadTy; 88959486a2dSAnders Carlsson FBadTy = llvm::FunctionType::get(ResultType, false); 89059486a2dSAnders Carlsson llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast"); 89159486a2dSAnders Carlsson Builder.CreateCall(F)->setDoesNotReturn(); 89259486a2dSAnders Carlsson Builder.CreateUnreachable(); 89359486a2dSAnders Carlsson } 89459486a2dSAnders Carlsson } 89559486a2dSAnders Carlsson 89659486a2dSAnders Carlsson if (CanBeZero) { 89759486a2dSAnders Carlsson Builder.CreateBr(ContBlock); 89859486a2dSAnders Carlsson EmitBlock(NullBlock); 89959486a2dSAnders Carlsson Builder.CreateBr(ContBlock); 90059486a2dSAnders Carlsson } 90159486a2dSAnders Carlsson EmitBlock(ContBlock); 90259486a2dSAnders Carlsson if (CanBeZero) { 90359486a2dSAnders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(LTy); 90459486a2dSAnders Carlsson PHI->reserveOperandSpace(2); 90559486a2dSAnders Carlsson PHI->addIncoming(V, NonZeroBlock); 90659486a2dSAnders Carlsson PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock); 90759486a2dSAnders Carlsson V = PHI; 90859486a2dSAnders Carlsson } 90959486a2dSAnders Carlsson 91059486a2dSAnders Carlsson return V; 91159486a2dSAnders Carlsson } 912