1*59486a2dSAnders Carlsson //===--- CGExprCXX.cpp - Emit LLVM Code for C++ expressions ---------------===// 2*59486a2dSAnders Carlsson // 3*59486a2dSAnders Carlsson // The LLVM Compiler Infrastructure 4*59486a2dSAnders Carlsson // 5*59486a2dSAnders Carlsson // This file is distributed under the University of Illinois Open Source 6*59486a2dSAnders Carlsson // License. See LICENSE.TXT for details. 7*59486a2dSAnders Carlsson // 8*59486a2dSAnders Carlsson //===----------------------------------------------------------------------===// 9*59486a2dSAnders Carlsson // 10*59486a2dSAnders Carlsson // This contains code dealing with code generation of C++ expressions 11*59486a2dSAnders Carlsson // 12*59486a2dSAnders Carlsson //===----------------------------------------------------------------------===// 13*59486a2dSAnders Carlsson 14*59486a2dSAnders Carlsson #include "CodeGenFunction.h" 15*59486a2dSAnders Carlsson using namespace clang; 16*59486a2dSAnders Carlsson using namespace CodeGen; 17*59486a2dSAnders Carlsson 18*59486a2dSAnders Carlsson static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) { 19*59486a2dSAnders Carlsson if (!E->isArray()) 20*59486a2dSAnders Carlsson return 0; 21*59486a2dSAnders Carlsson 22*59486a2dSAnders Carlsson QualType T = E->getAllocatedType(); 23*59486a2dSAnders Carlsson 24*59486a2dSAnders Carlsson const RecordType *RT = T->getAs<RecordType>(); 25*59486a2dSAnders Carlsson if (!RT) 26*59486a2dSAnders Carlsson return 0; 27*59486a2dSAnders Carlsson 28*59486a2dSAnders Carlsson const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()); 29*59486a2dSAnders Carlsson if (!RD) 30*59486a2dSAnders Carlsson return 0; 31*59486a2dSAnders Carlsson 32*59486a2dSAnders Carlsson // Check if the class has a trivial destructor. 33*59486a2dSAnders Carlsson if (RD->hasTrivialDestructor()) { 34*59486a2dSAnders Carlsson // FIXME: Check for a two-argument delete. 35*59486a2dSAnders Carlsson return 0; 36*59486a2dSAnders Carlsson } 37*59486a2dSAnders Carlsson 38*59486a2dSAnders Carlsson // Padding is the maximum of sizeof(size_t) and alignof(T) 39*59486a2dSAnders Carlsson return std::max(Ctx.getTypeSize(Ctx.getSizeType()), 40*59486a2dSAnders Carlsson static_cast<uint64_t>(Ctx.getTypeAlign(T))) / 8; 41*59486a2dSAnders Carlsson } 42*59486a2dSAnders Carlsson 43*59486a2dSAnders Carlsson static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF, 44*59486a2dSAnders Carlsson const CXXNewExpr *E, 45*59486a2dSAnders Carlsson llvm::Value *& NumElements) { 46*59486a2dSAnders Carlsson QualType Type = E->getAllocatedType(); 47*59486a2dSAnders Carlsson uint64_t TypeSizeInBytes = CGF.getContext().getTypeSize(Type) / 8; 48*59486a2dSAnders Carlsson const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); 49*59486a2dSAnders Carlsson 50*59486a2dSAnders Carlsson if (!E->isArray()) 51*59486a2dSAnders Carlsson return llvm::ConstantInt::get(SizeTy, TypeSizeInBytes); 52*59486a2dSAnders Carlsson 53*59486a2dSAnders Carlsson uint64_t CookiePadding = CalculateCookiePadding(CGF.getContext(), E); 54*59486a2dSAnders Carlsson 55*59486a2dSAnders Carlsson Expr::EvalResult Result; 56*59486a2dSAnders Carlsson if (E->getArraySize()->Evaluate(Result, CGF.getContext()) && 57*59486a2dSAnders Carlsson !Result.HasSideEffects && Result.Val.isInt()) { 58*59486a2dSAnders Carlsson 59*59486a2dSAnders Carlsson uint64_t AllocSize = 60*59486a2dSAnders Carlsson Result.Val.getInt().getZExtValue() * TypeSizeInBytes + CookiePadding; 61*59486a2dSAnders Carlsson 62*59486a2dSAnders Carlsson NumElements = 63*59486a2dSAnders Carlsson llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue()); 64*59486a2dSAnders Carlsson 65*59486a2dSAnders Carlsson return llvm::ConstantInt::get(SizeTy, AllocSize); 66*59486a2dSAnders Carlsson } 67*59486a2dSAnders Carlsson 68*59486a2dSAnders Carlsson // Emit the array size expression. 69*59486a2dSAnders Carlsson NumElements = CGF.EmitScalarExpr(E->getArraySize()); 70*59486a2dSAnders Carlsson 71*59486a2dSAnders Carlsson // Multiply with the type size. 72*59486a2dSAnders Carlsson llvm::Value *V = 73*59486a2dSAnders Carlsson CGF.Builder.CreateMul(NumElements, 74*59486a2dSAnders Carlsson llvm::ConstantInt::get(SizeTy, TypeSizeInBytes)); 75*59486a2dSAnders Carlsson 76*59486a2dSAnders Carlsson // And add the cookie padding if necessary. 77*59486a2dSAnders Carlsson if (CookiePadding) 78*59486a2dSAnders Carlsson V = CGF.Builder.CreateAdd(V, llvm::ConstantInt::get(SizeTy, CookiePadding)); 79*59486a2dSAnders Carlsson 80*59486a2dSAnders Carlsson return V; 81*59486a2dSAnders Carlsson } 82*59486a2dSAnders Carlsson 83*59486a2dSAnders Carlsson static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, 84*59486a2dSAnders Carlsson llvm::Value *NewPtr, 85*59486a2dSAnders Carlsson llvm::Value *NumElements) { 86*59486a2dSAnders Carlsson QualType AllocType = E->getAllocatedType(); 87*59486a2dSAnders Carlsson 88*59486a2dSAnders Carlsson if (!E->isArray()) { 89*59486a2dSAnders Carlsson if (CXXConstructorDecl *Ctor = E->getConstructor()) { 90*59486a2dSAnders Carlsson CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, 91*59486a2dSAnders Carlsson E->constructor_arg_begin(), 92*59486a2dSAnders Carlsson E->constructor_arg_end()); 93*59486a2dSAnders Carlsson 94*59486a2dSAnders Carlsson return; 95*59486a2dSAnders Carlsson } 96*59486a2dSAnders Carlsson 97*59486a2dSAnders Carlsson // We have a POD type. 98*59486a2dSAnders Carlsson if (E->getNumConstructorArgs() == 0) 99*59486a2dSAnders Carlsson return; 100*59486a2dSAnders Carlsson 101*59486a2dSAnders Carlsson assert(E->getNumConstructorArgs() == 1 && 102*59486a2dSAnders Carlsson "Can only have one argument to initializer of POD type."); 103*59486a2dSAnders Carlsson 104*59486a2dSAnders Carlsson const Expr *Init = E->getConstructorArg(0); 105*59486a2dSAnders Carlsson 106*59486a2dSAnders Carlsson if (!CGF.hasAggregateLLVMType(AllocType)) 107*59486a2dSAnders Carlsson CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr, 108*59486a2dSAnders Carlsson AllocType.isVolatileQualified(), AllocType); 109*59486a2dSAnders Carlsson else if (AllocType->isAnyComplexType()) 110*59486a2dSAnders Carlsson CGF.EmitComplexExprIntoAddr(Init, NewPtr, 111*59486a2dSAnders Carlsson AllocType.isVolatileQualified()); 112*59486a2dSAnders Carlsson else 113*59486a2dSAnders Carlsson CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); 114*59486a2dSAnders Carlsson return; 115*59486a2dSAnders Carlsson } 116*59486a2dSAnders Carlsson 117*59486a2dSAnders Carlsson if (CXXConstructorDecl *Ctor = E->getConstructor()) 118*59486a2dSAnders Carlsson CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr); 119*59486a2dSAnders Carlsson } 120*59486a2dSAnders Carlsson 121*59486a2dSAnders Carlsson llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) { 122*59486a2dSAnders Carlsson QualType AllocType = E->getAllocatedType(); 123*59486a2dSAnders Carlsson FunctionDecl *NewFD = E->getOperatorNew(); 124*59486a2dSAnders Carlsson const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>(); 125*59486a2dSAnders Carlsson 126*59486a2dSAnders Carlsson CallArgList NewArgs; 127*59486a2dSAnders Carlsson 128*59486a2dSAnders Carlsson // The allocation size is the first argument. 129*59486a2dSAnders Carlsson QualType SizeTy = getContext().getSizeType(); 130*59486a2dSAnders Carlsson 131*59486a2dSAnders Carlsson llvm::Value *NumElements = 0; 132*59486a2dSAnders Carlsson llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements); 133*59486a2dSAnders Carlsson 134*59486a2dSAnders Carlsson NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy)); 135*59486a2dSAnders Carlsson 136*59486a2dSAnders Carlsson // Emit the rest of the arguments. 137*59486a2dSAnders Carlsson // FIXME: Ideally, this should just use EmitCallArgs. 138*59486a2dSAnders Carlsson CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin(); 139*59486a2dSAnders Carlsson 140*59486a2dSAnders Carlsson // First, use the types from the function type. 141*59486a2dSAnders Carlsson // We start at 1 here because the first argument (the allocation size) 142*59486a2dSAnders Carlsson // has already been emitted. 143*59486a2dSAnders Carlsson for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) { 144*59486a2dSAnders Carlsson QualType ArgType = NewFTy->getArgType(i); 145*59486a2dSAnders Carlsson 146*59486a2dSAnders Carlsson assert(getContext().getCanonicalType(ArgType.getNonReferenceType()). 147*59486a2dSAnders Carlsson getTypePtr() == 148*59486a2dSAnders Carlsson getContext().getCanonicalType(NewArg->getType()).getTypePtr() && 149*59486a2dSAnders Carlsson "type mismatch in call argument!"); 150*59486a2dSAnders Carlsson 151*59486a2dSAnders Carlsson NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 152*59486a2dSAnders Carlsson ArgType)); 153*59486a2dSAnders Carlsson 154*59486a2dSAnders Carlsson } 155*59486a2dSAnders Carlsson 156*59486a2dSAnders Carlsson // Either we've emitted all the call args, or we have a call to a 157*59486a2dSAnders Carlsson // variadic function. 158*59486a2dSAnders Carlsson assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) && 159*59486a2dSAnders Carlsson "Extra arguments in non-variadic function!"); 160*59486a2dSAnders Carlsson 161*59486a2dSAnders Carlsson // If we still have any arguments, emit them using the type of the argument. 162*59486a2dSAnders Carlsson for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end(); 163*59486a2dSAnders Carlsson NewArg != NewArgEnd; ++NewArg) { 164*59486a2dSAnders Carlsson QualType ArgType = NewArg->getType(); 165*59486a2dSAnders Carlsson NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType), 166*59486a2dSAnders Carlsson ArgType)); 167*59486a2dSAnders Carlsson } 168*59486a2dSAnders Carlsson 169*59486a2dSAnders Carlsson // Emit the call to new. 170*59486a2dSAnders Carlsson RValue RV = 171*59486a2dSAnders Carlsson EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs), 172*59486a2dSAnders Carlsson CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD); 173*59486a2dSAnders Carlsson 174*59486a2dSAnders Carlsson // If an allocation function is declared with an empty exception specification 175*59486a2dSAnders Carlsson // it returns null to indicate failure to allocate storage. [expr.new]p13. 176*59486a2dSAnders Carlsson // (We don't need to check for null when there's no new initializer and 177*59486a2dSAnders Carlsson // we're allocating a POD type). 178*59486a2dSAnders Carlsson bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() && 179*59486a2dSAnders Carlsson !(AllocType->isPODType() && !E->hasInitializer()); 180*59486a2dSAnders Carlsson 181*59486a2dSAnders Carlsson llvm::BasicBlock *NewNull = 0; 182*59486a2dSAnders Carlsson llvm::BasicBlock *NewNotNull = 0; 183*59486a2dSAnders Carlsson llvm::BasicBlock *NewEnd = 0; 184*59486a2dSAnders Carlsson 185*59486a2dSAnders Carlsson llvm::Value *NewPtr = RV.getScalarVal(); 186*59486a2dSAnders Carlsson 187*59486a2dSAnders Carlsson if (NullCheckResult) { 188*59486a2dSAnders Carlsson NewNull = createBasicBlock("new.null"); 189*59486a2dSAnders Carlsson NewNotNull = createBasicBlock("new.notnull"); 190*59486a2dSAnders Carlsson NewEnd = createBasicBlock("new.end"); 191*59486a2dSAnders Carlsson 192*59486a2dSAnders Carlsson llvm::Value *IsNull = 193*59486a2dSAnders Carlsson Builder.CreateICmpEQ(NewPtr, 194*59486a2dSAnders Carlsson llvm::Constant::getNullValue(NewPtr->getType()), 195*59486a2dSAnders Carlsson "isnull"); 196*59486a2dSAnders Carlsson 197*59486a2dSAnders Carlsson Builder.CreateCondBr(IsNull, NewNull, NewNotNull); 198*59486a2dSAnders Carlsson EmitBlock(NewNotNull); 199*59486a2dSAnders Carlsson } 200*59486a2dSAnders Carlsson 201*59486a2dSAnders Carlsson if (uint64_t CookiePadding = CalculateCookiePadding(getContext(), E)) { 202*59486a2dSAnders Carlsson uint64_t CookieOffset = 203*59486a2dSAnders Carlsson CookiePadding - getContext().getTypeSize(SizeTy) / 8; 204*59486a2dSAnders Carlsson 205*59486a2dSAnders Carlsson llvm::Value *NumElementsPtr = 206*59486a2dSAnders Carlsson Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset); 207*59486a2dSAnders Carlsson 208*59486a2dSAnders Carlsson NumElementsPtr = Builder.CreateBitCast(NumElementsPtr, 209*59486a2dSAnders Carlsson ConvertType(SizeTy)->getPointerTo()); 210*59486a2dSAnders Carlsson Builder.CreateStore(NumElements, NumElementsPtr); 211*59486a2dSAnders Carlsson 212*59486a2dSAnders Carlsson // Now add the padding to the new ptr. 213*59486a2dSAnders Carlsson NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr, CookiePadding); 214*59486a2dSAnders Carlsson } 215*59486a2dSAnders Carlsson 216*59486a2dSAnders Carlsson NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType())); 217*59486a2dSAnders Carlsson 218*59486a2dSAnders Carlsson EmitNewInitializer(*this, E, NewPtr, NumElements); 219*59486a2dSAnders Carlsson 220*59486a2dSAnders Carlsson if (NullCheckResult) { 221*59486a2dSAnders Carlsson Builder.CreateBr(NewEnd); 222*59486a2dSAnders Carlsson NewNotNull = Builder.GetInsertBlock(); 223*59486a2dSAnders Carlsson EmitBlock(NewNull); 224*59486a2dSAnders Carlsson Builder.CreateBr(NewEnd); 225*59486a2dSAnders Carlsson EmitBlock(NewEnd); 226*59486a2dSAnders Carlsson 227*59486a2dSAnders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType()); 228*59486a2dSAnders Carlsson PHI->reserveOperandSpace(2); 229*59486a2dSAnders Carlsson PHI->addIncoming(NewPtr, NewNotNull); 230*59486a2dSAnders Carlsson PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull); 231*59486a2dSAnders Carlsson 232*59486a2dSAnders Carlsson NewPtr = PHI; 233*59486a2dSAnders Carlsson } 234*59486a2dSAnders Carlsson 235*59486a2dSAnders Carlsson return NewPtr; 236*59486a2dSAnders Carlsson } 237*59486a2dSAnders Carlsson 238*59486a2dSAnders Carlsson void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD, 239*59486a2dSAnders Carlsson llvm::Value *Ptr, 240*59486a2dSAnders Carlsson QualType DeleteTy) { 241*59486a2dSAnders Carlsson const FunctionProtoType *DeleteFTy = 242*59486a2dSAnders Carlsson DeleteFD->getType()->getAs<FunctionProtoType>(); 243*59486a2dSAnders Carlsson 244*59486a2dSAnders Carlsson CallArgList DeleteArgs; 245*59486a2dSAnders Carlsson 246*59486a2dSAnders Carlsson QualType ArgTy = DeleteFTy->getArgType(0); 247*59486a2dSAnders Carlsson llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy)); 248*59486a2dSAnders Carlsson DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy)); 249*59486a2dSAnders Carlsson 250*59486a2dSAnders Carlsson if (DeleteFTy->getNumArgs() == 2) { 251*59486a2dSAnders Carlsson QualType SizeTy = DeleteFTy->getArgType(1); 252*59486a2dSAnders Carlsson uint64_t SizeVal = getContext().getTypeSize(DeleteTy) / 8; 253*59486a2dSAnders Carlsson llvm::Constant *Size = llvm::ConstantInt::get(ConvertType(SizeTy), 254*59486a2dSAnders Carlsson SizeVal); 255*59486a2dSAnders Carlsson DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy)); 256*59486a2dSAnders Carlsson } 257*59486a2dSAnders Carlsson 258*59486a2dSAnders Carlsson // Emit the call to delete. 259*59486a2dSAnders Carlsson EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(), 260*59486a2dSAnders Carlsson DeleteArgs), 261*59486a2dSAnders Carlsson CGM.GetAddrOfFunction(DeleteFD), 262*59486a2dSAnders Carlsson DeleteArgs, DeleteFD); 263*59486a2dSAnders Carlsson } 264*59486a2dSAnders Carlsson 265*59486a2dSAnders Carlsson void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { 266*59486a2dSAnders Carlsson 267*59486a2dSAnders Carlsson // Get at the argument before we performed the implicit conversion 268*59486a2dSAnders Carlsson // to void*. 269*59486a2dSAnders Carlsson const Expr *Arg = E->getArgument(); 270*59486a2dSAnders Carlsson while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) { 271*59486a2dSAnders Carlsson if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion && 272*59486a2dSAnders Carlsson ICE->getType()->isVoidPointerType()) 273*59486a2dSAnders Carlsson Arg = ICE->getSubExpr(); 274*59486a2dSAnders Carlsson else 275*59486a2dSAnders Carlsson break; 276*59486a2dSAnders Carlsson } 277*59486a2dSAnders Carlsson 278*59486a2dSAnders Carlsson QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType(); 279*59486a2dSAnders Carlsson 280*59486a2dSAnders Carlsson llvm::Value *Ptr = EmitScalarExpr(Arg); 281*59486a2dSAnders Carlsson 282*59486a2dSAnders Carlsson // Null check the pointer. 283*59486a2dSAnders Carlsson llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull"); 284*59486a2dSAnders Carlsson llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end"); 285*59486a2dSAnders Carlsson 286*59486a2dSAnders Carlsson llvm::Value *IsNull = 287*59486a2dSAnders Carlsson Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()), 288*59486a2dSAnders Carlsson "isnull"); 289*59486a2dSAnders Carlsson 290*59486a2dSAnders Carlsson Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull); 291*59486a2dSAnders Carlsson EmitBlock(DeleteNotNull); 292*59486a2dSAnders Carlsson 293*59486a2dSAnders Carlsson bool ShouldCallDelete = true; 294*59486a2dSAnders Carlsson 295*59486a2dSAnders Carlsson // Call the destructor if necessary. 296*59486a2dSAnders Carlsson if (const RecordType *RT = DeleteTy->getAs<RecordType>()) { 297*59486a2dSAnders Carlsson if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { 298*59486a2dSAnders Carlsson if (!RD->hasTrivialDestructor()) { 299*59486a2dSAnders Carlsson const CXXDestructorDecl *Dtor = RD->getDestructor(getContext()); 300*59486a2dSAnders Carlsson if (E->isArrayForm()) { 301*59486a2dSAnders Carlsson QualType SizeTy = getContext().getSizeType(); 302*59486a2dSAnders Carlsson uint64_t CookiePadding = std::max(getContext().getTypeSize(SizeTy), 303*59486a2dSAnders Carlsson static_cast<uint64_t>(getContext().getTypeAlign(DeleteTy))) / 8; 304*59486a2dSAnders Carlsson if (CookiePadding) { 305*59486a2dSAnders Carlsson llvm::Type *Ptr8Ty = 306*59486a2dSAnders Carlsson llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0); 307*59486a2dSAnders Carlsson uint64_t CookieOffset = 308*59486a2dSAnders Carlsson CookiePadding - getContext().getTypeSize(SizeTy) / 8; 309*59486a2dSAnders Carlsson llvm::Value *AllocatedObjectPtr = 310*59486a2dSAnders Carlsson Builder.CreateConstInBoundsGEP1_64( 311*59486a2dSAnders Carlsson Builder.CreateBitCast(Ptr, Ptr8Ty), -CookiePadding); 312*59486a2dSAnders Carlsson llvm::Value *NumElementsPtr = 313*59486a2dSAnders Carlsson Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr, 314*59486a2dSAnders Carlsson CookieOffset); 315*59486a2dSAnders Carlsson NumElementsPtr = Builder.CreateBitCast(NumElementsPtr, 316*59486a2dSAnders Carlsson ConvertType(SizeTy)->getPointerTo()); 317*59486a2dSAnders Carlsson 318*59486a2dSAnders Carlsson llvm::Value *NumElements = 319*59486a2dSAnders Carlsson Builder.CreateLoad(NumElementsPtr); 320*59486a2dSAnders Carlsson NumElements = 321*59486a2dSAnders Carlsson Builder.CreateIntCast(NumElements, 322*59486a2dSAnders Carlsson llvm::Type::getInt64Ty(VMContext), false, 323*59486a2dSAnders Carlsson "count.tmp"); 324*59486a2dSAnders Carlsson EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr); 325*59486a2dSAnders Carlsson Ptr = AllocatedObjectPtr; 326*59486a2dSAnders Carlsson } 327*59486a2dSAnders Carlsson } 328*59486a2dSAnders Carlsson else if (Dtor->isVirtual()) { 329*59486a2dSAnders Carlsson const llvm::Type *Ty = 330*59486a2dSAnders Carlsson CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor), 331*59486a2dSAnders Carlsson /*isVariadic=*/false); 332*59486a2dSAnders Carlsson 333*59486a2dSAnders Carlsson llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty); 334*59486a2dSAnders Carlsson EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0); 335*59486a2dSAnders Carlsson 336*59486a2dSAnders Carlsson // The dtor took care of deleting the object. 337*59486a2dSAnders Carlsson ShouldCallDelete = false; 338*59486a2dSAnders Carlsson } else 339*59486a2dSAnders Carlsson EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr); 340*59486a2dSAnders Carlsson } 341*59486a2dSAnders Carlsson } 342*59486a2dSAnders Carlsson } 343*59486a2dSAnders Carlsson 344*59486a2dSAnders Carlsson if (ShouldCallDelete) 345*59486a2dSAnders Carlsson EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy); 346*59486a2dSAnders Carlsson 347*59486a2dSAnders Carlsson EmitBlock(DeleteEnd); 348*59486a2dSAnders Carlsson } 349*59486a2dSAnders Carlsson 350*59486a2dSAnders Carlsson llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) { 351*59486a2dSAnders Carlsson QualType Ty = E->getType(); 352*59486a2dSAnders Carlsson const llvm::Type *LTy = ConvertType(Ty)->getPointerTo(); 353*59486a2dSAnders Carlsson if (E->isTypeOperand()) { 354*59486a2dSAnders Carlsson Ty = E->getTypeOperand(); 355*59486a2dSAnders Carlsson CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); 356*59486a2dSAnders Carlsson Ty = CanTy.getUnqualifiedType().getNonReferenceType(); 357*59486a2dSAnders Carlsson if (const RecordType *RT = Ty->getAs<RecordType>()) { 358*59486a2dSAnders Carlsson const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 359*59486a2dSAnders Carlsson if (RD->isPolymorphic()) 360*59486a2dSAnders Carlsson return Builder.CreateBitCast(CGM.GenerateRttiRef(RD), LTy); 361*59486a2dSAnders Carlsson return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy); 362*59486a2dSAnders Carlsson } 363*59486a2dSAnders Carlsson return Builder.CreateBitCast(CGM.GenerateRtti(Ty), LTy); 364*59486a2dSAnders Carlsson } 365*59486a2dSAnders Carlsson Expr *subE = E->getExprOperand(); 366*59486a2dSAnders Carlsson Ty = subE->getType(); 367*59486a2dSAnders Carlsson CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); 368*59486a2dSAnders Carlsson Ty = CanTy.getUnqualifiedType().getNonReferenceType(); 369*59486a2dSAnders Carlsson if (const RecordType *RT = Ty->getAs<RecordType>()) { 370*59486a2dSAnders Carlsson const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); 371*59486a2dSAnders Carlsson if (RD->isPolymorphic()) { 372*59486a2dSAnders Carlsson // FIXME: if subE is an lvalue do 373*59486a2dSAnders Carlsson LValue Obj = EmitLValue(subE); 374*59486a2dSAnders Carlsson llvm::Value *This = Obj.getAddress(); 375*59486a2dSAnders Carlsson LTy = LTy->getPointerTo()->getPointerTo(); 376*59486a2dSAnders Carlsson llvm::Value *V = Builder.CreateBitCast(This, LTy); 377*59486a2dSAnders Carlsson // We need to do a zero check for *p, unless it has NonNullAttr. 378*59486a2dSAnders Carlsson // FIXME: PointerType->hasAttr<NonNullAttr>() 379*59486a2dSAnders Carlsson bool CanBeZero = false; 380*59486a2dSAnders Carlsson if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens())) 381*59486a2dSAnders Carlsson if (UO->getOpcode() == UnaryOperator::Deref) 382*59486a2dSAnders Carlsson CanBeZero = true; 383*59486a2dSAnders Carlsson if (CanBeZero) { 384*59486a2dSAnders Carlsson llvm::BasicBlock *NonZeroBlock = createBasicBlock(); 385*59486a2dSAnders Carlsson llvm::BasicBlock *ZeroBlock = createBasicBlock(); 386*59486a2dSAnders Carlsson 387*59486a2dSAnders Carlsson llvm::Value *Zero = llvm::Constant::getNullValue(LTy); 388*59486a2dSAnders Carlsson Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), 389*59486a2dSAnders Carlsson NonZeroBlock, ZeroBlock); 390*59486a2dSAnders Carlsson EmitBlock(ZeroBlock); 391*59486a2dSAnders Carlsson /// Call __cxa_bad_typeid 392*59486a2dSAnders Carlsson const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext); 393*59486a2dSAnders Carlsson const llvm::FunctionType *FTy; 394*59486a2dSAnders Carlsson FTy = llvm::FunctionType::get(ResultType, false); 395*59486a2dSAnders Carlsson llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid"); 396*59486a2dSAnders Carlsson Builder.CreateCall(F)->setDoesNotReturn(); 397*59486a2dSAnders Carlsson Builder.CreateUnreachable(); 398*59486a2dSAnders Carlsson EmitBlock(NonZeroBlock); 399*59486a2dSAnders Carlsson } 400*59486a2dSAnders Carlsson V = Builder.CreateLoad(V, "vtable"); 401*59486a2dSAnders Carlsson V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL); 402*59486a2dSAnders Carlsson V = Builder.CreateLoad(V); 403*59486a2dSAnders Carlsson return V; 404*59486a2dSAnders Carlsson } 405*59486a2dSAnders Carlsson return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy); 406*59486a2dSAnders Carlsson } 407*59486a2dSAnders Carlsson return Builder.CreateBitCast(CGM.GenerateRtti(Ty), LTy); 408*59486a2dSAnders Carlsson } 409*59486a2dSAnders Carlsson 410*59486a2dSAnders Carlsson llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V, 411*59486a2dSAnders Carlsson const CXXDynamicCastExpr *DCE) { 412*59486a2dSAnders Carlsson QualType CastTy = DCE->getTypeAsWritten(); 413*59486a2dSAnders Carlsson QualType InnerType = CastTy->getPointeeType(); 414*59486a2dSAnders Carlsson QualType ArgTy = DCE->getSubExpr()->getType(); 415*59486a2dSAnders Carlsson const llvm::Type *LArgTy = ConvertType(ArgTy); 416*59486a2dSAnders Carlsson const llvm::Type *LTy = ConvertType(DCE->getType()); 417*59486a2dSAnders Carlsson 418*59486a2dSAnders Carlsson bool CanBeZero = false; 419*59486a2dSAnders Carlsson bool ToVoid = false; 420*59486a2dSAnders Carlsson bool ThrowOnBad = false; 421*59486a2dSAnders Carlsson if (CastTy->isPointerType()) { 422*59486a2dSAnders Carlsson // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this 423*59486a2dSAnders Carlsson CanBeZero = true; 424*59486a2dSAnders Carlsson if (InnerType->isVoidType()) 425*59486a2dSAnders Carlsson ToVoid = true; 426*59486a2dSAnders Carlsson } else { 427*59486a2dSAnders Carlsson LTy = LTy->getPointerTo(); 428*59486a2dSAnders Carlsson ThrowOnBad = true; 429*59486a2dSAnders Carlsson } 430*59486a2dSAnders Carlsson 431*59486a2dSAnders Carlsson CXXRecordDecl *SrcTy; 432*59486a2dSAnders Carlsson QualType Ty = ArgTy; 433*59486a2dSAnders Carlsson if (ArgTy.getTypePtr()->isPointerType() 434*59486a2dSAnders Carlsson || ArgTy.getTypePtr()->isReferenceType()) 435*59486a2dSAnders Carlsson Ty = Ty.getTypePtr()->getPointeeType(); 436*59486a2dSAnders Carlsson CanQualType CanTy = CGM.getContext().getCanonicalType(Ty); 437*59486a2dSAnders Carlsson Ty = CanTy.getUnqualifiedType(); 438*59486a2dSAnders Carlsson SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); 439*59486a2dSAnders Carlsson 440*59486a2dSAnders Carlsson llvm::BasicBlock *ContBlock = createBasicBlock(); 441*59486a2dSAnders Carlsson llvm::BasicBlock *NullBlock = 0; 442*59486a2dSAnders Carlsson llvm::BasicBlock *NonZeroBlock = 0; 443*59486a2dSAnders Carlsson if (CanBeZero) { 444*59486a2dSAnders Carlsson NonZeroBlock = createBasicBlock(); 445*59486a2dSAnders Carlsson NullBlock = createBasicBlock(); 446*59486a2dSAnders Carlsson llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy); 447*59486a2dSAnders Carlsson Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), 448*59486a2dSAnders Carlsson NonZeroBlock, NullBlock); 449*59486a2dSAnders Carlsson EmitBlock(NonZeroBlock); 450*59486a2dSAnders Carlsson } 451*59486a2dSAnders Carlsson 452*59486a2dSAnders Carlsson llvm::BasicBlock *BadCastBlock = 0; 453*59486a2dSAnders Carlsson 454*59486a2dSAnders Carlsson const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType()); 455*59486a2dSAnders Carlsson 456*59486a2dSAnders Carlsson // See if this is a dynamic_cast(void*) 457*59486a2dSAnders Carlsson if (ToVoid) { 458*59486a2dSAnders Carlsson llvm::Value *This = V; 459*59486a2dSAnders Carlsson V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo()); 460*59486a2dSAnders Carlsson V = Builder.CreateLoad(V, "vtable"); 461*59486a2dSAnders Carlsson V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL); 462*59486a2dSAnders Carlsson V = Builder.CreateLoad(V, "offset to top"); 463*59486a2dSAnders Carlsson This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext)); 464*59486a2dSAnders Carlsson V = Builder.CreateInBoundsGEP(This, V); 465*59486a2dSAnders Carlsson V = Builder.CreateBitCast(V, LTy); 466*59486a2dSAnders Carlsson } else { 467*59486a2dSAnders Carlsson /// Call __dynamic_cast 468*59486a2dSAnders Carlsson const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext); 469*59486a2dSAnders Carlsson const llvm::FunctionType *FTy; 470*59486a2dSAnders Carlsson std::vector<const llvm::Type*> ArgTys; 471*59486a2dSAnders Carlsson const llvm::Type *PtrToInt8Ty 472*59486a2dSAnders Carlsson = llvm::Type::getInt8Ty(VMContext)->getPointerTo(); 473*59486a2dSAnders Carlsson ArgTys.push_back(PtrToInt8Ty); 474*59486a2dSAnders Carlsson ArgTys.push_back(PtrToInt8Ty); 475*59486a2dSAnders Carlsson ArgTys.push_back(PtrToInt8Ty); 476*59486a2dSAnders Carlsson ArgTys.push_back(PtrDiffTy); 477*59486a2dSAnders Carlsson FTy = llvm::FunctionType::get(ResultType, ArgTys, false); 478*59486a2dSAnders Carlsson CXXRecordDecl *DstTy; 479*59486a2dSAnders Carlsson Ty = CastTy.getTypePtr()->getPointeeType(); 480*59486a2dSAnders Carlsson CanTy = CGM.getContext().getCanonicalType(Ty); 481*59486a2dSAnders Carlsson Ty = CanTy.getUnqualifiedType(); 482*59486a2dSAnders Carlsson DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl()); 483*59486a2dSAnders Carlsson 484*59486a2dSAnders Carlsson // FIXME: Calculate better hint. 485*59486a2dSAnders Carlsson llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL); 486*59486a2dSAnders Carlsson llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy); 487*59486a2dSAnders Carlsson llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy); 488*59486a2dSAnders Carlsson V = Builder.CreateBitCast(V, PtrToInt8Ty); 489*59486a2dSAnders Carlsson V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"), 490*59486a2dSAnders Carlsson V, SrcArg, DstArg, hint); 491*59486a2dSAnders Carlsson V = Builder.CreateBitCast(V, LTy); 492*59486a2dSAnders Carlsson 493*59486a2dSAnders Carlsson if (ThrowOnBad) { 494*59486a2dSAnders Carlsson BadCastBlock = createBasicBlock(); 495*59486a2dSAnders Carlsson 496*59486a2dSAnders Carlsson llvm::Value *Zero = llvm::Constant::getNullValue(LTy); 497*59486a2dSAnders Carlsson Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero), 498*59486a2dSAnders Carlsson ContBlock, BadCastBlock); 499*59486a2dSAnders Carlsson EmitBlock(BadCastBlock); 500*59486a2dSAnders Carlsson /// Call __cxa_bad_cast 501*59486a2dSAnders Carlsson ResultType = llvm::Type::getVoidTy(VMContext); 502*59486a2dSAnders Carlsson const llvm::FunctionType *FBadTy; 503*59486a2dSAnders Carlsson FBadTy = llvm::FunctionType::get(ResultType, false); 504*59486a2dSAnders Carlsson llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast"); 505*59486a2dSAnders Carlsson Builder.CreateCall(F)->setDoesNotReturn(); 506*59486a2dSAnders Carlsson Builder.CreateUnreachable(); 507*59486a2dSAnders Carlsson } 508*59486a2dSAnders Carlsson } 509*59486a2dSAnders Carlsson 510*59486a2dSAnders Carlsson if (CanBeZero) { 511*59486a2dSAnders Carlsson Builder.CreateBr(ContBlock); 512*59486a2dSAnders Carlsson EmitBlock(NullBlock); 513*59486a2dSAnders Carlsson Builder.CreateBr(ContBlock); 514*59486a2dSAnders Carlsson } 515*59486a2dSAnders Carlsson EmitBlock(ContBlock); 516*59486a2dSAnders Carlsson if (CanBeZero) { 517*59486a2dSAnders Carlsson llvm::PHINode *PHI = Builder.CreatePHI(LTy); 518*59486a2dSAnders Carlsson PHI->reserveOperandSpace(2); 519*59486a2dSAnders Carlsson PHI->addIncoming(V, NonZeroBlock); 520*59486a2dSAnders Carlsson PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock); 521*59486a2dSAnders Carlsson V = PHI; 522*59486a2dSAnders Carlsson } 523*59486a2dSAnders Carlsson 524*59486a2dSAnders Carlsson return V; 525*59486a2dSAnders Carlsson } 526