blob: 54e6b0141fe8fdc44210175815b8b224ccb2ca49 [file] [log] [blame]
Anders Carlsson59486a22009-11-24 05:51:11 +00001//===--- CGExprCXX.cpp - Emit LLVM Code for C++ expressions ---------------===//
Anders Carlssoncc52f652009-09-22 22:53:17 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This contains code dealing with code generation of C++ expressions
11//
12//===----------------------------------------------------------------------===//
13
14#include "CodeGenFunction.h"
15using namespace clang;
16using namespace CodeGen;
17
Anders Carlsson21122cf2009-12-13 20:04:38 +000018static uint64_t CalculateCookiePadding(ASTContext &Ctx, QualType ElementType) {
19 const RecordType *RT = ElementType->getAs<RecordType>();
Anders Carlssonb4bd0662009-09-23 16:07:23 +000020 if (!RT)
21 return 0;
22
23 const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
24 if (!RD)
25 return 0;
26
27 // Check if the class has a trivial destructor.
28 if (RD->hasTrivialDestructor()) {
Anders Carlsson21122cf2009-12-13 20:04:38 +000029 // Check if the usual deallocation function takes two arguments.
Anders Carlssonadbe4242009-12-13 20:10:12 +000030 const CXXMethodDecl *UsualDeallocationFunction = 0;
31
Anders Carlsson21122cf2009-12-13 20:04:38 +000032 DeclarationName OpName =
33 Ctx.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
Anders Carlsson21122cf2009-12-13 20:04:38 +000034 DeclContext::lookup_const_iterator Op, OpEnd;
35 for (llvm::tie(Op, OpEnd) = RD->lookup(OpName);
36 Op != OpEnd; ++Op) {
Anders Carlssonadbe4242009-12-13 20:10:12 +000037 const CXXMethodDecl *Delete = cast<CXXMethodDecl>(*Op);
Anders Carlsson21122cf2009-12-13 20:04:38 +000038
39 if (Delete->isUsualDeallocationFunction()) {
Anders Carlssonadbe4242009-12-13 20:10:12 +000040 UsualDeallocationFunction = Delete;
Anders Carlsson21122cf2009-12-13 20:04:38 +000041 break;
42 }
43 }
Anders Carlssonadbe4242009-12-13 20:10:12 +000044
45 // No usual deallocation function, we don't need a cookie.
46 if (!UsualDeallocationFunction)
47 return 0;
48
49 // The usual deallocation function doesn't take a size_t argument, so we
50 // don't need a cookie.
51 if (UsualDeallocationFunction->getNumParams() == 1)
52 return 0;
53
54 assert(UsualDeallocationFunction->getNumParams() == 2 &&
55 "Unexpected deallocation function type!");
56 }
Anders Carlssonb4bd0662009-09-23 16:07:23 +000057
Anders Carlsson21122cf2009-12-13 20:04:38 +000058 // Padding is the maximum of sizeof(size_t) and alignof(ElementType)
Anders Carlssonb4bd0662009-09-23 16:07:23 +000059 return std::max(Ctx.getTypeSize(Ctx.getSizeType()),
Anders Carlsson21122cf2009-12-13 20:04:38 +000060 static_cast<uint64_t>(Ctx.getTypeAlign(ElementType))) / 8;
61}
62
63static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) {
64 if (!E->isArray())
65 return 0;
66
Anders Carlsson399f4992009-12-13 20:34:34 +000067 // No cookie is required if the new operator being used is
68 // ::operator new[](size_t, void*).
69 const FunctionDecl *OperatorNew = E->getOperatorNew();
70 if (OperatorNew->getDeclContext()->getLookupContext()->isFileContext()) {
71 if (OperatorNew->getNumParams() == 2) {
72 CanQualType ParamType =
73 Ctx.getCanonicalType(OperatorNew->getParamDecl(1)->getType());
74
75 if (ParamType == Ctx.VoidPtrTy)
76 return 0;
77 }
78 }
79
Anders Carlsson21122cf2009-12-13 20:04:38 +000080 return CalculateCookiePadding(Ctx, E->getAllocatedType());
81 QualType T = E->getAllocatedType();
Anders Carlssonb4bd0662009-09-23 16:07:23 +000082}
83
84static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
85 const CXXNewExpr *E,
86 llvm::Value *& NumElements) {
87 QualType Type = E->getAllocatedType();
88 uint64_t TypeSizeInBytes = CGF.getContext().getTypeSize(Type) / 8;
89 const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
90
91 if (!E->isArray())
92 return llvm::ConstantInt::get(SizeTy, TypeSizeInBytes);
93
94 uint64_t CookiePadding = CalculateCookiePadding(CGF.getContext(), E);
95
96 Expr::EvalResult Result;
97 if (E->getArraySize()->Evaluate(Result, CGF.getContext()) &&
98 !Result.HasSideEffects && Result.Val.isInt()) {
99
100 uint64_t AllocSize =
101 Result.Val.getInt().getZExtValue() * TypeSizeInBytes + CookiePadding;
102
103 NumElements =
104 llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue());
105
106 return llvm::ConstantInt::get(SizeTy, AllocSize);
107 }
108
109 // Emit the array size expression.
110 NumElements = CGF.EmitScalarExpr(E->getArraySize());
111
112 // Multiply with the type size.
113 llvm::Value *V =
114 CGF.Builder.CreateMul(NumElements,
115 llvm::ConstantInt::get(SizeTy, TypeSizeInBytes));
116
117 // And add the cookie padding if necessary.
118 if (CookiePadding)
119 V = CGF.Builder.CreateAdd(V, llvm::ConstantInt::get(SizeTy, CookiePadding));
120
121 return V;
122}
123
124static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
125 llvm::Value *NewPtr,
126 llvm::Value *NumElements) {
Anders Carlsson3a202f62009-11-24 18:43:52 +0000127 if (E->isArray()) {
128 if (CXXConstructorDecl *Ctor = E->getConstructor())
129 CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
130 E->constructor_arg_begin(),
131 E->constructor_arg_end());
Anders Carlssonb4bd0662009-09-23 16:07:23 +0000132 return;
133 }
134
Anders Carlsson3a202f62009-11-24 18:43:52 +0000135 QualType AllocType = E->getAllocatedType();
136
137 if (CXXConstructorDecl *Ctor = E->getConstructor()) {
138 CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
139 E->constructor_arg_begin(),
140 E->constructor_arg_end());
141
142 return;
143 }
144
145 // We have a POD type.
146 if (E->getNumConstructorArgs() == 0)
147 return;
148
149 assert(E->getNumConstructorArgs() == 1 &&
150 "Can only have one argument to initializer of POD type.");
151
152 const Expr *Init = E->getConstructorArg(0);
153
154 if (!CGF.hasAggregateLLVMType(AllocType))
155 CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
156 AllocType.isVolatileQualified(), AllocType);
157 else if (AllocType->isAnyComplexType())
158 CGF.EmitComplexExprIntoAddr(Init, NewPtr,
159 AllocType.isVolatileQualified());
160 else
161 CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
Anders Carlssonb4bd0662009-09-23 16:07:23 +0000162}
163
Anders Carlssoncc52f652009-09-22 22:53:17 +0000164llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
Anders Carlssoncc52f652009-09-22 22:53:17 +0000165 QualType AllocType = E->getAllocatedType();
166 FunctionDecl *NewFD = E->getOperatorNew();
167 const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>();
168
169 CallArgList NewArgs;
170
171 // The allocation size is the first argument.
172 QualType SizeTy = getContext().getSizeType();
Anders Carlssoncc52f652009-09-22 22:53:17 +0000173
Anders Carlssonb4bd0662009-09-23 16:07:23 +0000174 llvm::Value *NumElements = 0;
175 llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements);
176
Anders Carlssoncc52f652009-09-22 22:53:17 +0000177 NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
178
179 // Emit the rest of the arguments.
180 // FIXME: Ideally, this should just use EmitCallArgs.
181 CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin();
182
183 // First, use the types from the function type.
184 // We start at 1 here because the first argument (the allocation size)
185 // has already been emitted.
186 for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) {
187 QualType ArgType = NewFTy->getArgType(i);
188
189 assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
190 getTypePtr() ==
191 getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&
192 "type mismatch in call argument!");
193
194 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
195 ArgType));
196
197 }
198
199 // Either we've emitted all the call args, or we have a call to a
200 // variadic function.
201 assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&
202 "Extra arguments in non-variadic function!");
203
204 // If we still have any arguments, emit them using the type of the argument.
205 for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();
206 NewArg != NewArgEnd; ++NewArg) {
207 QualType ArgType = NewArg->getType();
208 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
209 ArgType));
210 }
211
212 // Emit the call to new.
213 RValue RV =
214 EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs),
215 CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD);
216
217 // If an allocation function is declared with an empty exception specification
218 // it returns null to indicate failure to allocate storage. [expr.new]p13.
219 // (We don't need to check for null when there's no new initializer and
220 // we're allocating a POD type).
221 bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
222 !(AllocType->isPODType() && !E->hasInitializer());
223
224 llvm::BasicBlock *NewNull = 0;
225 llvm::BasicBlock *NewNotNull = 0;
226 llvm::BasicBlock *NewEnd = 0;
227
228 llvm::Value *NewPtr = RV.getScalarVal();
229
230 if (NullCheckResult) {
231 NewNull = createBasicBlock("new.null");
232 NewNotNull = createBasicBlock("new.notnull");
233 NewEnd = createBasicBlock("new.end");
234
235 llvm::Value *IsNull =
236 Builder.CreateICmpEQ(NewPtr,
237 llvm::Constant::getNullValue(NewPtr->getType()),
238 "isnull");
239
240 Builder.CreateCondBr(IsNull, NewNull, NewNotNull);
241 EmitBlock(NewNotNull);
242 }
243
Anders Carlssonf7716812009-09-23 18:59:48 +0000244 if (uint64_t CookiePadding = CalculateCookiePadding(getContext(), E)) {
245 uint64_t CookieOffset =
246 CookiePadding - getContext().getTypeSize(SizeTy) / 8;
247
248 llvm::Value *NumElementsPtr =
249 Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset);
250
251 NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
252 ConvertType(SizeTy)->getPointerTo());
253 Builder.CreateStore(NumElements, NumElementsPtr);
254
255 // Now add the padding to the new ptr.
256 NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr, CookiePadding);
257 }
258
Anders Carlssoncc52f652009-09-22 22:53:17 +0000259 NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
260
Anders Carlssonb4bd0662009-09-23 16:07:23 +0000261 EmitNewInitializer(*this, E, NewPtr, NumElements);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000262
263 if (NullCheckResult) {
264 Builder.CreateBr(NewEnd);
Eli Friedman3ad26452009-11-10 22:39:09 +0000265 NewNotNull = Builder.GetInsertBlock();
Anders Carlssoncc52f652009-09-22 22:53:17 +0000266 EmitBlock(NewNull);
267 Builder.CreateBr(NewEnd);
268 EmitBlock(NewEnd);
269
270 llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
271 PHI->reserveOperandSpace(2);
272 PHI->addIncoming(NewPtr, NewNotNull);
273 PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull);
274
275 NewPtr = PHI;
276 }
277
278 return NewPtr;
279}
280
Anders Carlsson21122cf2009-12-13 20:04:38 +0000281static std::pair<llvm::Value *, llvm::Value *>
282GetAllocatedObjectPtrAndNumElements(CodeGenFunction &CGF,
283 llvm::Value *Ptr, QualType DeleteTy) {
284 QualType SizeTy = CGF.getContext().getSizeType();
285 const llvm::Type *SizeLTy = CGF.ConvertType(SizeTy);
286
287 uint64_t DeleteTypeAlign = CGF.getContext().getTypeAlign(DeleteTy);
288 uint64_t CookiePadding = std::max(CGF.getContext().getTypeSize(SizeTy),
289 DeleteTypeAlign) / 8;
290 assert(CookiePadding && "CookiePadding should not be 0.");
291
292 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
293 uint64_t CookieOffset =
294 CookiePadding - CGF.getContext().getTypeSize(SizeTy) / 8;
295
296 llvm::Value *AllocatedObjectPtr = CGF.Builder.CreateBitCast(Ptr, Int8PtrTy);
297 AllocatedObjectPtr =
298 CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
299 -CookiePadding);
300
301 llvm::Value *NumElementsPtr =
302 CGF.Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
303 CookieOffset);
304 NumElementsPtr =
305 CGF.Builder.CreateBitCast(NumElementsPtr, SizeLTy->getPointerTo());
306
307 llvm::Value *NumElements = CGF.Builder.CreateLoad(NumElementsPtr);
308 NumElements =
309 CGF.Builder.CreateIntCast(NumElements, SizeLTy, /*isSigned=*/false);
310
311 return std::make_pair(AllocatedObjectPtr, NumElements);
312}
313
Eli Friedmanfe81e3f2009-11-18 00:50:08 +0000314void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
315 llvm::Value *Ptr,
316 QualType DeleteTy) {
317 const FunctionProtoType *DeleteFTy =
318 DeleteFD->getType()->getAs<FunctionProtoType>();
319
320 CallArgList DeleteArgs;
321
Anders Carlsson21122cf2009-12-13 20:04:38 +0000322 // Check if we need to pass the size to the delete operator.
323 llvm::Value *Size = 0;
324 QualType SizeTy;
325 if (DeleteFTy->getNumArgs() == 2) {
326 SizeTy = DeleteFTy->getArgType(1);
327 uint64_t DeleteTypeSize = getContext().getTypeSize(DeleteTy) / 8;
328 Size = llvm::ConstantInt::get(ConvertType(SizeTy), DeleteTypeSize);
329 }
330
331 if (DeleteFD->getOverloadedOperator() == OO_Array_Delete &&
332
333 CalculateCookiePadding(getContext(), DeleteTy)) {
334 // We need to get the number of elements in the array from the cookie.
335 llvm::Value *AllocatedObjectPtr;
336 llvm::Value *NumElements;
337 llvm::tie(AllocatedObjectPtr, NumElements) =
338 GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy);
339
340 // Multiply the size with the number of elements.
341 if (Size)
342 Size = Builder.CreateMul(NumElements, Size);
343
344 Ptr = AllocatedObjectPtr;
345 }
346
Eli Friedmanfe81e3f2009-11-18 00:50:08 +0000347 QualType ArgTy = DeleteFTy->getArgType(0);
348 llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
349 DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
350
Anders Carlsson21122cf2009-12-13 20:04:38 +0000351 if (Size)
Eli Friedmanfe81e3f2009-11-18 00:50:08 +0000352 DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy));
Eli Friedmanfe81e3f2009-11-18 00:50:08 +0000353
354 // Emit the call to delete.
355 EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(),
356 DeleteArgs),
357 CGM.GetAddrOfFunction(DeleteFD),
358 DeleteArgs, DeleteFD);
359}
360
Anders Carlssoncc52f652009-09-22 22:53:17 +0000361void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
Fariborz Jahanian6814eaa2009-11-13 19:27:47 +0000362
Douglas Gregorbb3e12f2009-09-29 18:16:17 +0000363 // Get at the argument before we performed the implicit conversion
364 // to void*.
365 const Expr *Arg = E->getArgument();
366 while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
367 if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion &&
368 ICE->getType()->isVoidPointerType())
369 Arg = ICE->getSubExpr();
Douglas Gregore364e7b2009-10-01 05:49:51 +0000370 else
371 break;
Douglas Gregorbb3e12f2009-09-29 18:16:17 +0000372 }
373
374 QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
Anders Carlssoncc52f652009-09-22 22:53:17 +0000375
Douglas Gregorbb3e12f2009-09-29 18:16:17 +0000376 llvm::Value *Ptr = EmitScalarExpr(Arg);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000377
378 // Null check the pointer.
379 llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");
380 llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");
381
382 llvm::Value *IsNull =
383 Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()),
384 "isnull");
385
386 Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
387 EmitBlock(DeleteNotNull);
Anders Carlssone828c362009-11-13 04:45:41 +0000388
389 bool ShouldCallDelete = true;
390
Anders Carlssoncc52f652009-09-22 22:53:17 +0000391 // Call the destructor if necessary.
392 if (const RecordType *RT = DeleteTy->getAs<RecordType>()) {
393 if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
394 if (!RD->hasTrivialDestructor()) {
395 const CXXDestructorDecl *Dtor = RD->getDestructor(getContext());
Fariborz Jahanian6814eaa2009-11-13 19:27:47 +0000396 if (E->isArrayForm()) {
Anders Carlsson21122cf2009-12-13 20:04:38 +0000397 llvm::Value *AllocatedObjectPtr;
398 llvm::Value *NumElements;
399 llvm::tie(AllocatedObjectPtr, NumElements) =
400 GetAllocatedObjectPtrAndNumElements(*this, Ptr, DeleteTy);
401
Anders Carlssonf5af8de2009-12-13 18:48:07 +0000402 EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr);
Anders Carlssonf5af8de2009-12-13 18:48:07 +0000403 } else if (Dtor->isVirtual()) {
Anders Carlssoncc52f652009-09-22 22:53:17 +0000404 const llvm::Type *Ty =
405 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor),
406 /*isVariadic=*/false);
407
Anders Carlssone828c362009-11-13 04:45:41 +0000408 llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000409 EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0);
Anders Carlssone828c362009-11-13 04:45:41 +0000410
411 // The dtor took care of deleting the object.
412 ShouldCallDelete = false;
Anders Carlssoncc52f652009-09-22 22:53:17 +0000413 } else
414 EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr);
415 }
416 }
417 }
418
Eli Friedmanfe81e3f2009-11-18 00:50:08 +0000419 if (ShouldCallDelete)
420 EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000421
Anders Carlssoncc52f652009-09-22 22:53:17 +0000422 EmitBlock(DeleteEnd);
423}
Mike Stumpc9b231c2009-11-15 08:09:41 +0000424
425llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
426 QualType Ty = E->getType();
427 const llvm::Type *LTy = ConvertType(Ty)->getPointerTo();
Anders Carlssonfd7dfeb2009-12-11 02:46:30 +0000428
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000429 if (E->isTypeOperand()) {
430 llvm::Constant *TypeInfo =
431 CGM.GetAddrOfRTTIDescriptor(E->getTypeOperand());
432 return Builder.CreateBitCast(TypeInfo, LTy);
433 }
434
Mike Stumpc9b231c2009-11-15 08:09:41 +0000435 Expr *subE = E->getExprOperand();
Mike Stump6fdfea62009-11-17 22:33:00 +0000436 Ty = subE->getType();
437 CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
438 Ty = CanTy.getUnqualifiedType().getNonReferenceType();
Mike Stumpc9b231c2009-11-15 08:09:41 +0000439 if (const RecordType *RT = Ty->getAs<RecordType>()) {
440 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
441 if (RD->isPolymorphic()) {
442 // FIXME: if subE is an lvalue do
443 LValue Obj = EmitLValue(subE);
444 llvm::Value *This = Obj.getAddress();
Mike Stump1bf924b2009-11-15 16:52:53 +0000445 LTy = LTy->getPointerTo()->getPointerTo();
446 llvm::Value *V = Builder.CreateBitCast(This, LTy);
447 // We need to do a zero check for *p, unless it has NonNullAttr.
448 // FIXME: PointerType->hasAttr<NonNullAttr>()
449 bool CanBeZero = false;
Mike Stumpc2c03342009-11-17 00:45:21 +0000450 if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens()))
Mike Stump1bf924b2009-11-15 16:52:53 +0000451 if (UO->getOpcode() == UnaryOperator::Deref)
452 CanBeZero = true;
453 if (CanBeZero) {
454 llvm::BasicBlock *NonZeroBlock = createBasicBlock();
455 llvm::BasicBlock *ZeroBlock = createBasicBlock();
456
457 llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
458 Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
459 NonZeroBlock, ZeroBlock);
460 EmitBlock(ZeroBlock);
461 /// Call __cxa_bad_typeid
462 const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
463 const llvm::FunctionType *FTy;
464 FTy = llvm::FunctionType::get(ResultType, false);
465 llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
Mike Stump65511702009-11-16 06:50:58 +0000466 Builder.CreateCall(F)->setDoesNotReturn();
Mike Stump1bf924b2009-11-15 16:52:53 +0000467 Builder.CreateUnreachable();
468 EmitBlock(NonZeroBlock);
469 }
Mike Stumpc9b231c2009-11-15 08:09:41 +0000470 V = Builder.CreateLoad(V, "vtable");
471 V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL);
472 V = Builder.CreateLoad(V);
473 return V;
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000474 }
Mike Stumpc9b231c2009-11-15 08:09:41 +0000475 }
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000476 return Builder.CreateBitCast(CGM.GetAddrOfRTTIDescriptor(Ty), LTy);
Mike Stumpc9b231c2009-11-15 08:09:41 +0000477}
Mike Stump65511702009-11-16 06:50:58 +0000478
479llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
480 const CXXDynamicCastExpr *DCE) {
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000481 QualType SrcTy = DCE->getSubExpr()->getType();
482 QualType DestTy = DCE->getTypeAsWritten();
483 QualType InnerType = DestTy->getPointeeType();
484
Mike Stump65511702009-11-16 06:50:58 +0000485 const llvm::Type *LTy = ConvertType(DCE->getType());
Mike Stump6ca0e212009-11-16 22:52:20 +0000486
Mike Stump65511702009-11-16 06:50:58 +0000487 bool CanBeZero = false;
Mike Stump65511702009-11-16 06:50:58 +0000488 bool ToVoid = false;
Mike Stump6ca0e212009-11-16 22:52:20 +0000489 bool ThrowOnBad = false;
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000490 if (DestTy->isPointerType()) {
Mike Stump65511702009-11-16 06:50:58 +0000491 // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
492 CanBeZero = true;
493 if (InnerType->isVoidType())
494 ToVoid = true;
495 } else {
496 LTy = LTy->getPointerTo();
497 ThrowOnBad = true;
498 }
499
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000500 if (SrcTy->isPointerType() || SrcTy->isReferenceType())
501 SrcTy = SrcTy->getPointeeType();
502 SrcTy = SrcTy.getUnqualifiedType();
503
Anders Carlsson0087bc82009-12-18 14:55:04 +0000504 if (DestTy->isPointerType() || DestTy->isReferenceType())
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000505 DestTy = DestTy->getPointeeType();
506 DestTy = DestTy.getUnqualifiedType();
Mike Stump65511702009-11-16 06:50:58 +0000507
Mike Stump65511702009-11-16 06:50:58 +0000508 llvm::BasicBlock *ContBlock = createBasicBlock();
509 llvm::BasicBlock *NullBlock = 0;
510 llvm::BasicBlock *NonZeroBlock = 0;
511 if (CanBeZero) {
512 NonZeroBlock = createBasicBlock();
513 NullBlock = createBasicBlock();
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000514 Builder.CreateCondBr(Builder.CreateIsNotNull(V), NonZeroBlock, NullBlock);
Mike Stump65511702009-11-16 06:50:58 +0000515 EmitBlock(NonZeroBlock);
516 }
517
Mike Stump65511702009-11-16 06:50:58 +0000518 llvm::BasicBlock *BadCastBlock = 0;
Mike Stump65511702009-11-16 06:50:58 +0000519
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000520 const llvm::Type *PtrDiffTy = ConvertType(getContext().getPointerDiffType());
Mike Stump6ca0e212009-11-16 22:52:20 +0000521
522 // See if this is a dynamic_cast(void*)
523 if (ToVoid) {
524 llvm::Value *This = V;
525 V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo());
526 V = Builder.CreateLoad(V, "vtable");
527 V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL);
528 V = Builder.CreateLoad(V, "offset to top");
529 This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext));
530 V = Builder.CreateInBoundsGEP(This, V);
531 V = Builder.CreateBitCast(V, LTy);
532 } else {
533 /// Call __dynamic_cast
534 const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
535 const llvm::FunctionType *FTy;
536 std::vector<const llvm::Type*> ArgTys;
537 const llvm::Type *PtrToInt8Ty
538 = llvm::Type::getInt8Ty(VMContext)->getPointerTo();
539 ArgTys.push_back(PtrToInt8Ty);
540 ArgTys.push_back(PtrToInt8Ty);
541 ArgTys.push_back(PtrToInt8Ty);
542 ArgTys.push_back(PtrDiffTy);
543 FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
Mike Stump6ca0e212009-11-16 22:52:20 +0000544
545 // FIXME: Calculate better hint.
546 llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000547
548 assert(SrcTy->isRecordType() && "Src type must be record type!");
549 assert(DestTy->isRecordType() && "Dest type must be record type!");
550
Douglas Gregor247894b2009-12-23 22:04:40 +0000551 llvm::Value *SrcArg
552 = CGM.GetAddrOfRTTIDescriptor(SrcTy.getUnqualifiedType());
553 llvm::Value *DestArg
554 = CGM.GetAddrOfRTTIDescriptor(DestTy.getUnqualifiedType());
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000555
Mike Stump6ca0e212009-11-16 22:52:20 +0000556 V = Builder.CreateBitCast(V, PtrToInt8Ty);
557 V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000558 V, SrcArg, DestArg, hint);
Mike Stump6ca0e212009-11-16 22:52:20 +0000559 V = Builder.CreateBitCast(V, LTy);
560
561 if (ThrowOnBad) {
562 BadCastBlock = createBasicBlock();
563
Anders Carlsson3f4336c2009-12-17 07:09:17 +0000564 Builder.CreateCondBr(Builder.CreateIsNotNull(V), ContBlock, BadCastBlock);
Mike Stump6ca0e212009-11-16 22:52:20 +0000565 EmitBlock(BadCastBlock);
566 /// Call __cxa_bad_cast
567 ResultType = llvm::Type::getVoidTy(VMContext);
568 const llvm::FunctionType *FBadTy;
Mike Stump3afea1d2009-11-17 03:01:03 +0000569 FBadTy = llvm::FunctionType::get(ResultType, false);
Mike Stump6ca0e212009-11-16 22:52:20 +0000570 llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
571 Builder.CreateCall(F)->setDoesNotReturn();
Mike Stumpe8cdcc92009-11-17 00:08:50 +0000572 Builder.CreateUnreachable();
Mike Stump6ca0e212009-11-16 22:52:20 +0000573 }
Mike Stump65511702009-11-16 06:50:58 +0000574 }
575
576 if (CanBeZero) {
577 Builder.CreateBr(ContBlock);
578 EmitBlock(NullBlock);
579 Builder.CreateBr(ContBlock);
580 }
581 EmitBlock(ContBlock);
582 if (CanBeZero) {
583 llvm::PHINode *PHI = Builder.CreatePHI(LTy);
Mike Stump4d0e9092009-11-17 00:10:05 +0000584 PHI->reserveOperandSpace(2);
Mike Stump65511702009-11-16 06:50:58 +0000585 PHI->addIncoming(V, NonZeroBlock);
586 PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
Mike Stump65511702009-11-16 06:50:58 +0000587 V = PHI;
588 }
589
590 return V;
591}