blob: 048e9de4993024a653ffb6e904dddaa54dbf96ff [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 Carlssonb4bd0662009-09-23 16:07:23 +000018static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) {
Anders Carlssonf7716812009-09-23 18:59:48 +000019 if (!E->isArray())
20 return 0;
21
Anders Carlssonb4bd0662009-09-23 16:07:23 +000022 QualType T = E->getAllocatedType();
23
24 const RecordType *RT = T->getAs<RecordType>();
25 if (!RT)
26 return 0;
27
28 const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl());
29 if (!RD)
30 return 0;
31
32 // Check if the class has a trivial destructor.
33 if (RD->hasTrivialDestructor()) {
34 // FIXME: Check for a two-argument delete.
35 return 0;
36 }
37
38 // Padding is the maximum of sizeof(size_t) and alignof(T)
39 return std::max(Ctx.getTypeSize(Ctx.getSizeType()),
Anders Carlssonf7716812009-09-23 18:59:48 +000040 static_cast<uint64_t>(Ctx.getTypeAlign(T))) / 8;
Anders Carlssonb4bd0662009-09-23 16:07:23 +000041}
42
43static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
44 const CXXNewExpr *E,
45 llvm::Value *& NumElements) {
46 QualType Type = E->getAllocatedType();
47 uint64_t TypeSizeInBytes = CGF.getContext().getTypeSize(Type) / 8;
48 const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType());
49
50 if (!E->isArray())
51 return llvm::ConstantInt::get(SizeTy, TypeSizeInBytes);
52
53 uint64_t CookiePadding = CalculateCookiePadding(CGF.getContext(), E);
54
55 Expr::EvalResult Result;
56 if (E->getArraySize()->Evaluate(Result, CGF.getContext()) &&
57 !Result.HasSideEffects && Result.Val.isInt()) {
58
59 uint64_t AllocSize =
60 Result.Val.getInt().getZExtValue() * TypeSizeInBytes + CookiePadding;
61
62 NumElements =
63 llvm::ConstantInt::get(SizeTy, Result.Val.getInt().getZExtValue());
64
65 return llvm::ConstantInt::get(SizeTy, AllocSize);
66 }
67
68 // Emit the array size expression.
69 NumElements = CGF.EmitScalarExpr(E->getArraySize());
70
71 // Multiply with the type size.
72 llvm::Value *V =
73 CGF.Builder.CreateMul(NumElements,
74 llvm::ConstantInt::get(SizeTy, TypeSizeInBytes));
75
76 // And add the cookie padding if necessary.
77 if (CookiePadding)
78 V = CGF.Builder.CreateAdd(V, llvm::ConstantInt::get(SizeTy, CookiePadding));
79
80 return V;
81}
82
83static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E,
84 llvm::Value *NewPtr,
85 llvm::Value *NumElements) {
86 QualType AllocType = E->getAllocatedType();
87
88 if (!E->isArray()) {
89 if (CXXConstructorDecl *Ctor = E->getConstructor()) {
90 CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
91 E->constructor_arg_begin(),
92 E->constructor_arg_end());
93
94 return;
95 }
96
97 // We have a POD type.
98 if (E->getNumConstructorArgs() == 0)
99 return;
100
101 assert(E->getNumConstructorArgs() == 1 &&
102 "Can only have one argument to initializer of POD type.");
103
104 const Expr *Init = E->getConstructorArg(0);
105
Anders Carlsson58381082009-11-22 19:25:33 +0000106 if (!CGF.hasAggregateLLVMType(AllocType))
107 CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
108 AllocType.isVolatileQualified(), AllocType);
Anders Carlssonb4bd0662009-09-23 16:07:23 +0000109 else if (AllocType->isAnyComplexType())
110 CGF.EmitComplexExprIntoAddr(Init, NewPtr,
111 AllocType.isVolatileQualified());
112 else
113 CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
114 return;
115 }
116
117 if (CXXConstructorDecl *Ctor = E->getConstructor())
118 CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr);
119}
120
Anders Carlssoncc52f652009-09-22 22:53:17 +0000121llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
Anders Carlssoncc52f652009-09-22 22:53:17 +0000122 QualType AllocType = E->getAllocatedType();
123 FunctionDecl *NewFD = E->getOperatorNew();
124 const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>();
125
126 CallArgList NewArgs;
127
128 // The allocation size is the first argument.
129 QualType SizeTy = getContext().getSizeType();
Anders Carlssoncc52f652009-09-22 22:53:17 +0000130
Anders Carlssonb4bd0662009-09-23 16:07:23 +0000131 llvm::Value *NumElements = 0;
132 llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements);
133
Anders Carlssoncc52f652009-09-22 22:53:17 +0000134 NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
135
136 // Emit the rest of the arguments.
137 // FIXME: Ideally, this should just use EmitCallArgs.
138 CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin();
139
140 // First, use the types from the function type.
141 // We start at 1 here because the first argument (the allocation size)
142 // has already been emitted.
143 for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) {
144 QualType ArgType = NewFTy->getArgType(i);
145
146 assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
147 getTypePtr() ==
148 getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&
149 "type mismatch in call argument!");
150
151 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
152 ArgType));
153
154 }
155
156 // Either we've emitted all the call args, or we have a call to a
157 // variadic function.
158 assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&
159 "Extra arguments in non-variadic function!");
160
161 // If we still have any arguments, emit them using the type of the argument.
162 for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();
163 NewArg != NewArgEnd; ++NewArg) {
164 QualType ArgType = NewArg->getType();
165 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
166 ArgType));
167 }
168
169 // Emit the call to new.
170 RValue RV =
171 EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs),
172 CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD);
173
174 // If an allocation function is declared with an empty exception specification
175 // it returns null to indicate failure to allocate storage. [expr.new]p13.
176 // (We don't need to check for null when there's no new initializer and
177 // we're allocating a POD type).
178 bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
179 !(AllocType->isPODType() && !E->hasInitializer());
180
181 llvm::BasicBlock *NewNull = 0;
182 llvm::BasicBlock *NewNotNull = 0;
183 llvm::BasicBlock *NewEnd = 0;
184
185 llvm::Value *NewPtr = RV.getScalarVal();
186
187 if (NullCheckResult) {
188 NewNull = createBasicBlock("new.null");
189 NewNotNull = createBasicBlock("new.notnull");
190 NewEnd = createBasicBlock("new.end");
191
192 llvm::Value *IsNull =
193 Builder.CreateICmpEQ(NewPtr,
194 llvm::Constant::getNullValue(NewPtr->getType()),
195 "isnull");
196
197 Builder.CreateCondBr(IsNull, NewNull, NewNotNull);
198 EmitBlock(NewNotNull);
199 }
200
Anders Carlssonf7716812009-09-23 18:59:48 +0000201 if (uint64_t CookiePadding = CalculateCookiePadding(getContext(), E)) {
202 uint64_t CookieOffset =
203 CookiePadding - getContext().getTypeSize(SizeTy) / 8;
204
205 llvm::Value *NumElementsPtr =
206 Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset);
207
208 NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
209 ConvertType(SizeTy)->getPointerTo());
210 Builder.CreateStore(NumElements, NumElementsPtr);
211
212 // Now add the padding to the new ptr.
213 NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr, CookiePadding);
214 }
215
Anders Carlssoncc52f652009-09-22 22:53:17 +0000216 NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
217
Anders Carlssonb4bd0662009-09-23 16:07:23 +0000218 EmitNewInitializer(*this, E, NewPtr, NumElements);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000219
220 if (NullCheckResult) {
221 Builder.CreateBr(NewEnd);
Eli Friedman3ad26452009-11-10 22:39:09 +0000222 NewNotNull = Builder.GetInsertBlock();
Anders Carlssoncc52f652009-09-22 22:53:17 +0000223 EmitBlock(NewNull);
224 Builder.CreateBr(NewEnd);
225 EmitBlock(NewEnd);
226
227 llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
228 PHI->reserveOperandSpace(2);
229 PHI->addIncoming(NewPtr, NewNotNull);
230 PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull);
231
232 NewPtr = PHI;
233 }
234
235 return NewPtr;
236}
237
Eli Friedmanfe81e3f2009-11-18 00:50:08 +0000238void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
239 llvm::Value *Ptr,
240 QualType DeleteTy) {
241 const FunctionProtoType *DeleteFTy =
242 DeleteFD->getType()->getAs<FunctionProtoType>();
243
244 CallArgList DeleteArgs;
245
246 QualType ArgTy = DeleteFTy->getArgType(0);
247 llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
248 DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
249
250 if (DeleteFTy->getNumArgs() == 2) {
251 QualType SizeTy = DeleteFTy->getArgType(1);
252 uint64_t SizeVal = getContext().getTypeSize(DeleteTy) / 8;
253 llvm::Constant *Size = llvm::ConstantInt::get(ConvertType(SizeTy),
254 SizeVal);
255 DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy));
256 }
257
258 // Emit the call to delete.
259 EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(),
260 DeleteArgs),
261 CGM.GetAddrOfFunction(DeleteFD),
262 DeleteArgs, DeleteFD);
263}
264
Anders Carlssoncc52f652009-09-22 22:53:17 +0000265void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
Fariborz Jahanian6814eaa2009-11-13 19:27:47 +0000266
Douglas Gregorbb3e12f2009-09-29 18:16:17 +0000267 // Get at the argument before we performed the implicit conversion
268 // to void*.
269 const Expr *Arg = E->getArgument();
270 while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
271 if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion &&
272 ICE->getType()->isVoidPointerType())
273 Arg = ICE->getSubExpr();
Douglas Gregore364e7b2009-10-01 05:49:51 +0000274 else
275 break;
Douglas Gregorbb3e12f2009-09-29 18:16:17 +0000276 }
277
278 QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
Anders Carlssoncc52f652009-09-22 22:53:17 +0000279
Douglas Gregorbb3e12f2009-09-29 18:16:17 +0000280 llvm::Value *Ptr = EmitScalarExpr(Arg);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000281
282 // Null check the pointer.
283 llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");
284 llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");
285
286 llvm::Value *IsNull =
287 Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()),
288 "isnull");
289
290 Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
291 EmitBlock(DeleteNotNull);
Anders Carlssone828c362009-11-13 04:45:41 +0000292
293 bool ShouldCallDelete = true;
294
Anders Carlssoncc52f652009-09-22 22:53:17 +0000295 // Call the destructor if necessary.
296 if (const RecordType *RT = DeleteTy->getAs<RecordType>()) {
297 if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
298 if (!RD->hasTrivialDestructor()) {
299 const CXXDestructorDecl *Dtor = RD->getDestructor(getContext());
Fariborz Jahanian6814eaa2009-11-13 19:27:47 +0000300 if (E->isArrayForm()) {
301 QualType SizeTy = getContext().getSizeType();
302 uint64_t CookiePadding = std::max(getContext().getTypeSize(SizeTy),
303 static_cast<uint64_t>(getContext().getTypeAlign(DeleteTy))) / 8;
304 if (CookiePadding) {
305 llvm::Type *Ptr8Ty =
306 llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
307 uint64_t CookieOffset =
308 CookiePadding - getContext().getTypeSize(SizeTy) / 8;
309 llvm::Value *AllocatedObjectPtr =
310 Builder.CreateConstInBoundsGEP1_64(
311 Builder.CreateBitCast(Ptr, Ptr8Ty), -CookiePadding);
312 llvm::Value *NumElementsPtr =
313 Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
314 CookieOffset);
Fariborz Jahanianf75c1f72009-11-13 21:20:14 +0000315 NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
316 ConvertType(SizeTy)->getPointerTo());
Fariborz Jahanian6814eaa2009-11-13 19:27:47 +0000317
Fariborz Jahanian6814eaa2009-11-13 19:27:47 +0000318 llvm::Value *NumElements =
319 Builder.CreateLoad(NumElementsPtr);
Fariborz Jahanianf75c1f72009-11-13 21:20:14 +0000320 NumElements =
321 Builder.CreateIntCast(NumElements,
322 llvm::Type::getInt64Ty(VMContext), false,
323 "count.tmp");
Fariborz Jahanian6814eaa2009-11-13 19:27:47 +0000324 EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr);
325 Ptr = AllocatedObjectPtr;
326 }
327 }
328 else if (Dtor->isVirtual()) {
Anders Carlssoncc52f652009-09-22 22:53:17 +0000329 const llvm::Type *Ty =
330 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor),
331 /*isVariadic=*/false);
332
Anders Carlssone828c362009-11-13 04:45:41 +0000333 llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000334 EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0);
Anders Carlssone828c362009-11-13 04:45:41 +0000335
336 // The dtor took care of deleting the object.
337 ShouldCallDelete = false;
Anders Carlssoncc52f652009-09-22 22:53:17 +0000338 } else
339 EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr);
340 }
341 }
342 }
343
Eli Friedmanfe81e3f2009-11-18 00:50:08 +0000344 if (ShouldCallDelete)
345 EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy);
Anders Carlssoncc52f652009-09-22 22:53:17 +0000346
Anders Carlssoncc52f652009-09-22 22:53:17 +0000347 EmitBlock(DeleteEnd);
348}
Mike Stumpc9b231c2009-11-15 08:09:41 +0000349
350llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
351 QualType Ty = E->getType();
352 const llvm::Type *LTy = ConvertType(Ty)->getPointerTo();
353 if (E->isTypeOperand()) {
Mike Stump3f75d552009-11-17 02:16:21 +0000354 Ty = E->getTypeOperand();
Mike Stump4ac39ef2009-11-15 20:30:39 +0000355 CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
356 Ty = CanTy.getUnqualifiedType().getNonReferenceType();
Mike Stumpc9b231c2009-11-15 08:09:41 +0000357 if (const RecordType *RT = Ty->getAs<RecordType>()) {
358 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
359 if (RD->isPolymorphic())
360 return Builder.CreateBitCast(CGM.GenerateRttiRef(RD), LTy);
361 return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy);
362 }
Mike Stump101f0522009-11-20 00:31:50 +0000363 return Builder.CreateBitCast(CGM.GenerateRtti(Ty), LTy);
Mike Stumpc9b231c2009-11-15 08:09:41 +0000364 }
365 Expr *subE = E->getExprOperand();
Mike Stump6fdfea62009-11-17 22:33:00 +0000366 Ty = subE->getType();
367 CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
368 Ty = CanTy.getUnqualifiedType().getNonReferenceType();
Mike Stumpc9b231c2009-11-15 08:09:41 +0000369 if (const RecordType *RT = Ty->getAs<RecordType>()) {
370 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
371 if (RD->isPolymorphic()) {
372 // FIXME: if subE is an lvalue do
373 LValue Obj = EmitLValue(subE);
374 llvm::Value *This = Obj.getAddress();
Mike Stump1bf924b2009-11-15 16:52:53 +0000375 LTy = LTy->getPointerTo()->getPointerTo();
376 llvm::Value *V = Builder.CreateBitCast(This, LTy);
377 // We need to do a zero check for *p, unless it has NonNullAttr.
378 // FIXME: PointerType->hasAttr<NonNullAttr>()
379 bool CanBeZero = false;
Mike Stumpc2c03342009-11-17 00:45:21 +0000380 if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens()))
Mike Stump1bf924b2009-11-15 16:52:53 +0000381 if (UO->getOpcode() == UnaryOperator::Deref)
382 CanBeZero = true;
383 if (CanBeZero) {
384 llvm::BasicBlock *NonZeroBlock = createBasicBlock();
385 llvm::BasicBlock *ZeroBlock = createBasicBlock();
386
387 llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
388 Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
389 NonZeroBlock, ZeroBlock);
390 EmitBlock(ZeroBlock);
391 /// Call __cxa_bad_typeid
392 const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
393 const llvm::FunctionType *FTy;
394 FTy = llvm::FunctionType::get(ResultType, false);
395 llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
Mike Stump65511702009-11-16 06:50:58 +0000396 Builder.CreateCall(F)->setDoesNotReturn();
Mike Stump1bf924b2009-11-15 16:52:53 +0000397 Builder.CreateUnreachable();
398 EmitBlock(NonZeroBlock);
399 }
Mike Stumpc9b231c2009-11-15 08:09:41 +0000400 V = Builder.CreateLoad(V, "vtable");
401 V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL);
402 V = Builder.CreateLoad(V);
403 return V;
404 }
Mike Stump3f75d552009-11-17 02:16:21 +0000405 return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy);
Mike Stumpc9b231c2009-11-15 08:09:41 +0000406 }
Mike Stump101f0522009-11-20 00:31:50 +0000407 return Builder.CreateBitCast(CGM.GenerateRtti(Ty), LTy);
Mike Stumpc9b231c2009-11-15 08:09:41 +0000408}
Mike Stump65511702009-11-16 06:50:58 +0000409
410llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
411 const CXXDynamicCastExpr *DCE) {
412 QualType CastTy = DCE->getTypeAsWritten();
Mike Stump6ca0e212009-11-16 22:52:20 +0000413 QualType InnerType = CastTy->getPointeeType();
Mike Stump65511702009-11-16 06:50:58 +0000414 QualType ArgTy = DCE->getSubExpr()->getType();
415 const llvm::Type *LArgTy = ConvertType(ArgTy);
416 const llvm::Type *LTy = ConvertType(DCE->getType());
Mike Stump6ca0e212009-11-16 22:52:20 +0000417
Mike Stump65511702009-11-16 06:50:58 +0000418 bool CanBeZero = false;
Mike Stump65511702009-11-16 06:50:58 +0000419 bool ToVoid = false;
Mike Stump6ca0e212009-11-16 22:52:20 +0000420 bool ThrowOnBad = false;
Mike Stump65511702009-11-16 06:50:58 +0000421 if (CastTy->isPointerType()) {
422 // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
423 CanBeZero = true;
424 if (InnerType->isVoidType())
425 ToVoid = true;
426 } else {
427 LTy = LTy->getPointerTo();
428 ThrowOnBad = true;
429 }
430
Mike Stump6ca0e212009-11-16 22:52:20 +0000431 CXXRecordDecl *SrcTy;
432 QualType Ty = ArgTy;
433 if (ArgTy.getTypePtr()->isPointerType()
434 || ArgTy.getTypePtr()->isReferenceType())
435 Ty = Ty.getTypePtr()->getPointeeType();
436 CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
437 Ty = CanTy.getUnqualifiedType();
438 SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
Mike Stump65511702009-11-16 06:50:58 +0000439
Mike Stump65511702009-11-16 06:50:58 +0000440 llvm::BasicBlock *ContBlock = createBasicBlock();
441 llvm::BasicBlock *NullBlock = 0;
442 llvm::BasicBlock *NonZeroBlock = 0;
443 if (CanBeZero) {
444 NonZeroBlock = createBasicBlock();
445 NullBlock = createBasicBlock();
446 llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy);
447 Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
448 NonZeroBlock, NullBlock);
449 EmitBlock(NonZeroBlock);
450 }
451
Mike Stump65511702009-11-16 06:50:58 +0000452 llvm::BasicBlock *BadCastBlock = 0;
Mike Stump65511702009-11-16 06:50:58 +0000453
Mike Stump6ca0e212009-11-16 22:52:20 +0000454 const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType());
455
456 // See if this is a dynamic_cast(void*)
457 if (ToVoid) {
458 llvm::Value *This = V;
459 V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo());
460 V = Builder.CreateLoad(V, "vtable");
461 V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL);
462 V = Builder.CreateLoad(V, "offset to top");
463 This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext));
464 V = Builder.CreateInBoundsGEP(This, V);
465 V = Builder.CreateBitCast(V, LTy);
466 } else {
467 /// Call __dynamic_cast
468 const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
469 const llvm::FunctionType *FTy;
470 std::vector<const llvm::Type*> ArgTys;
471 const llvm::Type *PtrToInt8Ty
472 = llvm::Type::getInt8Ty(VMContext)->getPointerTo();
473 ArgTys.push_back(PtrToInt8Ty);
474 ArgTys.push_back(PtrToInt8Ty);
475 ArgTys.push_back(PtrToInt8Ty);
476 ArgTys.push_back(PtrDiffTy);
477 FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
478 CXXRecordDecl *DstTy;
479 Ty = CastTy.getTypePtr()->getPointeeType();
480 CanTy = CGM.getContext().getCanonicalType(Ty);
481 Ty = CanTy.getUnqualifiedType();
482 DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
483
484 // FIXME: Calculate better hint.
485 llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
486 llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy);
487 llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy);
488 V = Builder.CreateBitCast(V, PtrToInt8Ty);
489 V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
490 V, SrcArg, DstArg, hint);
491 V = Builder.CreateBitCast(V, LTy);
492
493 if (ThrowOnBad) {
494 BadCastBlock = createBasicBlock();
495
496 llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
497 Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
498 ContBlock, BadCastBlock);
499 EmitBlock(BadCastBlock);
500 /// Call __cxa_bad_cast
501 ResultType = llvm::Type::getVoidTy(VMContext);
502 const llvm::FunctionType *FBadTy;
Mike Stump3afea1d2009-11-17 03:01:03 +0000503 FBadTy = llvm::FunctionType::get(ResultType, false);
Mike Stump6ca0e212009-11-16 22:52:20 +0000504 llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
505 Builder.CreateCall(F)->setDoesNotReturn();
Mike Stumpe8cdcc92009-11-17 00:08:50 +0000506 Builder.CreateUnreachable();
Mike Stump6ca0e212009-11-16 22:52:20 +0000507 }
Mike Stump65511702009-11-16 06:50:58 +0000508 }
509
510 if (CanBeZero) {
511 Builder.CreateBr(ContBlock);
512 EmitBlock(NullBlock);
513 Builder.CreateBr(ContBlock);
514 }
515 EmitBlock(ContBlock);
516 if (CanBeZero) {
517 llvm::PHINode *PHI = Builder.CreatePHI(LTy);
Mike Stump4d0e9092009-11-17 00:10:05 +0000518 PHI->reserveOperandSpace(2);
Mike Stump65511702009-11-16 06:50:58 +0000519 PHI->addIncoming(V, NonZeroBlock);
520 PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
Mike Stump65511702009-11-16 06:50:58 +0000521 V = PHI;
522 }
523
524 return V;
525}