blob: b982c15683ecec8006b95f758faeb2ca8e8f4471 [file] [log] [blame]
Anders Carlsson5b955922009-11-24 05:51:11 +00001//===--- CGExprCXX.cpp - Emit LLVM Code for C++ expressions ---------------===//
Anders Carlsson16d81b82009-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 Carlssona4d4c012009-09-23 16:07:23 +000018static uint64_t CalculateCookiePadding(ASTContext &Ctx, const CXXNewExpr *E) {
Anders Carlsson6ac5fc42009-09-23 18:59:48 +000019 if (!E->isArray())
20 return 0;
21
Anders Carlssona4d4c012009-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 Carlsson6ac5fc42009-09-23 18:59:48 +000040 static_cast<uint64_t>(Ctx.getTypeAlign(T))) / 8;
Anders Carlssona4d4c012009-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) {
Anders Carlsson5d4d9462009-11-24 18:43:52 +000086 if (E->isArray()) {
87 if (CXXConstructorDecl *Ctor = E->getConstructor())
88 CGF.EmitCXXAggrConstructorCall(Ctor, NumElements, NewPtr,
89 E->constructor_arg_begin(),
90 E->constructor_arg_end());
Anders Carlssona4d4c012009-09-23 16:07:23 +000091 return;
92 }
93
Anders Carlsson5d4d9462009-11-24 18:43:52 +000094 QualType AllocType = E->getAllocatedType();
95
96 if (CXXConstructorDecl *Ctor = E->getConstructor()) {
97 CGF.EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr,
98 E->constructor_arg_begin(),
99 E->constructor_arg_end());
100
101 return;
102 }
103
104 // We have a POD type.
105 if (E->getNumConstructorArgs() == 0)
106 return;
107
108 assert(E->getNumConstructorArgs() == 1 &&
109 "Can only have one argument to initializer of POD type.");
110
111 const Expr *Init = E->getConstructorArg(0);
112
113 if (!CGF.hasAggregateLLVMType(AllocType))
114 CGF.EmitStoreOfScalar(CGF.EmitScalarExpr(Init), NewPtr,
115 AllocType.isVolatileQualified(), AllocType);
116 else if (AllocType->isAnyComplexType())
117 CGF.EmitComplexExprIntoAddr(Init, NewPtr,
118 AllocType.isVolatileQualified());
119 else
120 CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
Anders Carlssona4d4c012009-09-23 16:07:23 +0000121}
122
Anders Carlsson16d81b82009-09-22 22:53:17 +0000123llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
Anders Carlsson16d81b82009-09-22 22:53:17 +0000124 QualType AllocType = E->getAllocatedType();
125 FunctionDecl *NewFD = E->getOperatorNew();
126 const FunctionProtoType *NewFTy = NewFD->getType()->getAs<FunctionProtoType>();
127
128 CallArgList NewArgs;
129
130 // The allocation size is the first argument.
131 QualType SizeTy = getContext().getSizeType();
Anders Carlsson16d81b82009-09-22 22:53:17 +0000132
Anders Carlssona4d4c012009-09-23 16:07:23 +0000133 llvm::Value *NumElements = 0;
134 llvm::Value *AllocSize = EmitCXXNewAllocSize(*this, E, NumElements);
135
Anders Carlsson16d81b82009-09-22 22:53:17 +0000136 NewArgs.push_back(std::make_pair(RValue::get(AllocSize), SizeTy));
137
138 // Emit the rest of the arguments.
139 // FIXME: Ideally, this should just use EmitCallArgs.
140 CXXNewExpr::const_arg_iterator NewArg = E->placement_arg_begin();
141
142 // First, use the types from the function type.
143 // We start at 1 here because the first argument (the allocation size)
144 // has already been emitted.
145 for (unsigned i = 1, e = NewFTy->getNumArgs(); i != e; ++i, ++NewArg) {
146 QualType ArgType = NewFTy->getArgType(i);
147
148 assert(getContext().getCanonicalType(ArgType.getNonReferenceType()).
149 getTypePtr() ==
150 getContext().getCanonicalType(NewArg->getType()).getTypePtr() &&
151 "type mismatch in call argument!");
152
153 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
154 ArgType));
155
156 }
157
158 // Either we've emitted all the call args, or we have a call to a
159 // variadic function.
160 assert((NewArg == E->placement_arg_end() || NewFTy->isVariadic()) &&
161 "Extra arguments in non-variadic function!");
162
163 // If we still have any arguments, emit them using the type of the argument.
164 for (CXXNewExpr::const_arg_iterator NewArgEnd = E->placement_arg_end();
165 NewArg != NewArgEnd; ++NewArg) {
166 QualType ArgType = NewArg->getType();
167 NewArgs.push_back(std::make_pair(EmitCallArg(*NewArg, ArgType),
168 ArgType));
169 }
170
171 // Emit the call to new.
172 RValue RV =
173 EmitCall(CGM.getTypes().getFunctionInfo(NewFTy->getResultType(), NewArgs),
174 CGM.GetAddrOfFunction(NewFD), NewArgs, NewFD);
175
176 // If an allocation function is declared with an empty exception specification
177 // it returns null to indicate failure to allocate storage. [expr.new]p13.
178 // (We don't need to check for null when there's no new initializer and
179 // we're allocating a POD type).
180 bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
181 !(AllocType->isPODType() && !E->hasInitializer());
182
183 llvm::BasicBlock *NewNull = 0;
184 llvm::BasicBlock *NewNotNull = 0;
185 llvm::BasicBlock *NewEnd = 0;
186
187 llvm::Value *NewPtr = RV.getScalarVal();
188
189 if (NullCheckResult) {
190 NewNull = createBasicBlock("new.null");
191 NewNotNull = createBasicBlock("new.notnull");
192 NewEnd = createBasicBlock("new.end");
193
194 llvm::Value *IsNull =
195 Builder.CreateICmpEQ(NewPtr,
196 llvm::Constant::getNullValue(NewPtr->getType()),
197 "isnull");
198
199 Builder.CreateCondBr(IsNull, NewNull, NewNotNull);
200 EmitBlock(NewNotNull);
201 }
202
Anders Carlsson6ac5fc42009-09-23 18:59:48 +0000203 if (uint64_t CookiePadding = CalculateCookiePadding(getContext(), E)) {
204 uint64_t CookieOffset =
205 CookiePadding - getContext().getTypeSize(SizeTy) / 8;
206
207 llvm::Value *NumElementsPtr =
208 Builder.CreateConstInBoundsGEP1_64(NewPtr, CookieOffset);
209
210 NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
211 ConvertType(SizeTy)->getPointerTo());
212 Builder.CreateStore(NumElements, NumElementsPtr);
213
214 // Now add the padding to the new ptr.
215 NewPtr = Builder.CreateConstInBoundsGEP1_64(NewPtr, CookiePadding);
216 }
217
Anders Carlsson16d81b82009-09-22 22:53:17 +0000218 NewPtr = Builder.CreateBitCast(NewPtr, ConvertType(E->getType()));
219
Anders Carlssona4d4c012009-09-23 16:07:23 +0000220 EmitNewInitializer(*this, E, NewPtr, NumElements);
Anders Carlsson16d81b82009-09-22 22:53:17 +0000221
222 if (NullCheckResult) {
223 Builder.CreateBr(NewEnd);
Eli Friedman7f1de452009-11-10 22:39:09 +0000224 NewNotNull = Builder.GetInsertBlock();
Anders Carlsson16d81b82009-09-22 22:53:17 +0000225 EmitBlock(NewNull);
226 Builder.CreateBr(NewEnd);
227 EmitBlock(NewEnd);
228
229 llvm::PHINode *PHI = Builder.CreatePHI(NewPtr->getType());
230 PHI->reserveOperandSpace(2);
231 PHI->addIncoming(NewPtr, NewNotNull);
232 PHI->addIncoming(llvm::Constant::getNullValue(NewPtr->getType()), NewNull);
233
234 NewPtr = PHI;
235 }
236
237 return NewPtr;
238}
239
Eli Friedman5fe05982009-11-18 00:50:08 +0000240void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
241 llvm::Value *Ptr,
242 QualType DeleteTy) {
243 const FunctionProtoType *DeleteFTy =
244 DeleteFD->getType()->getAs<FunctionProtoType>();
245
246 CallArgList DeleteArgs;
247
248 QualType ArgTy = DeleteFTy->getArgType(0);
249 llvm::Value *DeletePtr = Builder.CreateBitCast(Ptr, ConvertType(ArgTy));
250 DeleteArgs.push_back(std::make_pair(RValue::get(DeletePtr), ArgTy));
251
252 if (DeleteFTy->getNumArgs() == 2) {
253 QualType SizeTy = DeleteFTy->getArgType(1);
254 uint64_t SizeVal = getContext().getTypeSize(DeleteTy) / 8;
255 llvm::Constant *Size = llvm::ConstantInt::get(ConvertType(SizeTy),
256 SizeVal);
257 DeleteArgs.push_back(std::make_pair(RValue::get(Size), SizeTy));
258 }
259
260 // Emit the call to delete.
261 EmitCall(CGM.getTypes().getFunctionInfo(DeleteFTy->getResultType(),
262 DeleteArgs),
263 CGM.GetAddrOfFunction(DeleteFD),
264 DeleteArgs, DeleteFD);
265}
266
Anders Carlsson16d81b82009-09-22 22:53:17 +0000267void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
Fariborz Jahanian72c21532009-11-13 19:27:47 +0000268
Douglas Gregor90916562009-09-29 18:16:17 +0000269 // Get at the argument before we performed the implicit conversion
270 // to void*.
271 const Expr *Arg = E->getArgument();
272 while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
273 if (ICE->getCastKind() != CastExpr::CK_UserDefinedConversion &&
274 ICE->getType()->isVoidPointerType())
275 Arg = ICE->getSubExpr();
Douglas Gregord69dd782009-10-01 05:49:51 +0000276 else
277 break;
Douglas Gregor90916562009-09-29 18:16:17 +0000278 }
279
280 QualType DeleteTy = Arg->getType()->getAs<PointerType>()->getPointeeType();
Anders Carlsson16d81b82009-09-22 22:53:17 +0000281
Douglas Gregor90916562009-09-29 18:16:17 +0000282 llvm::Value *Ptr = EmitScalarExpr(Arg);
Anders Carlsson16d81b82009-09-22 22:53:17 +0000283
284 // Null check the pointer.
285 llvm::BasicBlock *DeleteNotNull = createBasicBlock("delete.notnull");
286 llvm::BasicBlock *DeleteEnd = createBasicBlock("delete.end");
287
288 llvm::Value *IsNull =
289 Builder.CreateICmpEQ(Ptr, llvm::Constant::getNullValue(Ptr->getType()),
290 "isnull");
291
292 Builder.CreateCondBr(IsNull, DeleteEnd, DeleteNotNull);
293 EmitBlock(DeleteNotNull);
Anders Carlsson566abee2009-11-13 04:45:41 +0000294
295 bool ShouldCallDelete = true;
296
Anders Carlsson16d81b82009-09-22 22:53:17 +0000297 // Call the destructor if necessary.
298 if (const RecordType *RT = DeleteTy->getAs<RecordType>()) {
299 if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) {
300 if (!RD->hasTrivialDestructor()) {
301 const CXXDestructorDecl *Dtor = RD->getDestructor(getContext());
Fariborz Jahanian72c21532009-11-13 19:27:47 +0000302 if (E->isArrayForm()) {
303 QualType SizeTy = getContext().getSizeType();
304 uint64_t CookiePadding = std::max(getContext().getTypeSize(SizeTy),
305 static_cast<uint64_t>(getContext().getTypeAlign(DeleteTy))) / 8;
306 if (CookiePadding) {
307 llvm::Type *Ptr8Ty =
308 llvm::PointerType::get(llvm::Type::getInt8Ty(VMContext), 0);
309 uint64_t CookieOffset =
310 CookiePadding - getContext().getTypeSize(SizeTy) / 8;
311 llvm::Value *AllocatedObjectPtr =
312 Builder.CreateConstInBoundsGEP1_64(
313 Builder.CreateBitCast(Ptr, Ptr8Ty), -CookiePadding);
314 llvm::Value *NumElementsPtr =
315 Builder.CreateConstInBoundsGEP1_64(AllocatedObjectPtr,
316 CookieOffset);
Fariborz Jahanian6fb98d92009-11-13 21:20:14 +0000317 NumElementsPtr = Builder.CreateBitCast(NumElementsPtr,
318 ConvertType(SizeTy)->getPointerTo());
Fariborz Jahanian72c21532009-11-13 19:27:47 +0000319
Fariborz Jahanian72c21532009-11-13 19:27:47 +0000320 llvm::Value *NumElements =
321 Builder.CreateLoad(NumElementsPtr);
Fariborz Jahanian6fb98d92009-11-13 21:20:14 +0000322 NumElements =
323 Builder.CreateIntCast(NumElements,
324 llvm::Type::getInt64Ty(VMContext), false,
325 "count.tmp");
Fariborz Jahanian72c21532009-11-13 19:27:47 +0000326 EmitCXXAggrDestructorCall(Dtor, NumElements, Ptr);
327 Ptr = AllocatedObjectPtr;
328 }
329 }
330 else if (Dtor->isVirtual()) {
Anders Carlsson16d81b82009-09-22 22:53:17 +0000331 const llvm::Type *Ty =
332 CGM.getTypes().GetFunctionType(CGM.getTypes().getFunctionInfo(Dtor),
333 /*isVariadic=*/false);
334
Anders Carlsson566abee2009-11-13 04:45:41 +0000335 llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
Anders Carlsson16d81b82009-09-22 22:53:17 +0000336 EmitCXXMemberCall(Dtor, Callee, Ptr, 0, 0);
Anders Carlsson566abee2009-11-13 04:45:41 +0000337
338 // The dtor took care of deleting the object.
339 ShouldCallDelete = false;
Anders Carlsson16d81b82009-09-22 22:53:17 +0000340 } else
341 EmitCXXDestructorCall(Dtor, Dtor_Complete, Ptr);
342 }
343 }
344 }
345
Eli Friedman5fe05982009-11-18 00:50:08 +0000346 if (ShouldCallDelete)
347 EmitDeleteCall(E->getOperatorDelete(), Ptr, DeleteTy);
Anders Carlsson16d81b82009-09-22 22:53:17 +0000348
Anders Carlsson16d81b82009-09-22 22:53:17 +0000349 EmitBlock(DeleteEnd);
350}
Mike Stumpc2e84ae2009-11-15 08:09:41 +0000351
352llvm::Value * CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
353 QualType Ty = E->getType();
354 const llvm::Type *LTy = ConvertType(Ty)->getPointerTo();
355 if (E->isTypeOperand()) {
Mike Stumpea2c0b52009-11-17 02:16:21 +0000356 Ty = E->getTypeOperand();
Mike Stump80556322009-11-15 20:30:39 +0000357 CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
358 Ty = CanTy.getUnqualifiedType().getNonReferenceType();
Mike Stumpc2e84ae2009-11-15 08:09:41 +0000359 if (const RecordType *RT = Ty->getAs<RecordType>()) {
360 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
361 if (RD->isPolymorphic())
362 return Builder.CreateBitCast(CGM.GenerateRttiRef(RD), LTy);
363 return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy);
364 }
Mike Stump7e1365a2009-11-20 00:31:50 +0000365 return Builder.CreateBitCast(CGM.GenerateRtti(Ty), LTy);
Mike Stumpc2e84ae2009-11-15 08:09:41 +0000366 }
367 Expr *subE = E->getExprOperand();
Mike Stump5fae8562009-11-17 22:33:00 +0000368 Ty = subE->getType();
369 CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
370 Ty = CanTy.getUnqualifiedType().getNonReferenceType();
Mike Stumpc2e84ae2009-11-15 08:09:41 +0000371 if (const RecordType *RT = Ty->getAs<RecordType>()) {
372 const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
373 if (RD->isPolymorphic()) {
374 // FIXME: if subE is an lvalue do
375 LValue Obj = EmitLValue(subE);
376 llvm::Value *This = Obj.getAddress();
Mike Stumpf549e892009-11-15 16:52:53 +0000377 LTy = LTy->getPointerTo()->getPointerTo();
378 llvm::Value *V = Builder.CreateBitCast(This, LTy);
379 // We need to do a zero check for *p, unless it has NonNullAttr.
380 // FIXME: PointerType->hasAttr<NonNullAttr>()
381 bool CanBeZero = false;
Mike Stumpdb519a42009-11-17 00:45:21 +0000382 if (UnaryOperator *UO = dyn_cast<UnaryOperator>(subE->IgnoreParens()))
Mike Stumpf549e892009-11-15 16:52:53 +0000383 if (UO->getOpcode() == UnaryOperator::Deref)
384 CanBeZero = true;
385 if (CanBeZero) {
386 llvm::BasicBlock *NonZeroBlock = createBasicBlock();
387 llvm::BasicBlock *ZeroBlock = createBasicBlock();
388
389 llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
390 Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
391 NonZeroBlock, ZeroBlock);
392 EmitBlock(ZeroBlock);
393 /// Call __cxa_bad_typeid
394 const llvm::Type *ResultType = llvm::Type::getVoidTy(VMContext);
395 const llvm::FunctionType *FTy;
396 FTy = llvm::FunctionType::get(ResultType, false);
397 llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
Mike Stumpc849c052009-11-16 06:50:58 +0000398 Builder.CreateCall(F)->setDoesNotReturn();
Mike Stumpf549e892009-11-15 16:52:53 +0000399 Builder.CreateUnreachable();
400 EmitBlock(NonZeroBlock);
401 }
Mike Stumpc2e84ae2009-11-15 08:09:41 +0000402 V = Builder.CreateLoad(V, "vtable");
403 V = Builder.CreateConstInBoundsGEP1_64(V, -1ULL);
404 V = Builder.CreateLoad(V);
405 return V;
406 }
Mike Stumpea2c0b52009-11-17 02:16:21 +0000407 return Builder.CreateBitCast(CGM.GenerateRtti(RD), LTy);
Mike Stumpc2e84ae2009-11-15 08:09:41 +0000408 }
Mike Stump7e1365a2009-11-20 00:31:50 +0000409 return Builder.CreateBitCast(CGM.GenerateRtti(Ty), LTy);
Mike Stumpc2e84ae2009-11-15 08:09:41 +0000410}
Mike Stumpc849c052009-11-16 06:50:58 +0000411
412llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
413 const CXXDynamicCastExpr *DCE) {
414 QualType CastTy = DCE->getTypeAsWritten();
Mike Stump2b35baf2009-11-16 22:52:20 +0000415 QualType InnerType = CastTy->getPointeeType();
Mike Stumpc849c052009-11-16 06:50:58 +0000416 QualType ArgTy = DCE->getSubExpr()->getType();
417 const llvm::Type *LArgTy = ConvertType(ArgTy);
418 const llvm::Type *LTy = ConvertType(DCE->getType());
Mike Stump2b35baf2009-11-16 22:52:20 +0000419
Mike Stumpc849c052009-11-16 06:50:58 +0000420 bool CanBeZero = false;
Mike Stumpc849c052009-11-16 06:50:58 +0000421 bool ToVoid = false;
Mike Stump2b35baf2009-11-16 22:52:20 +0000422 bool ThrowOnBad = false;
Mike Stumpc849c052009-11-16 06:50:58 +0000423 if (CastTy->isPointerType()) {
424 // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
425 CanBeZero = true;
426 if (InnerType->isVoidType())
427 ToVoid = true;
428 } else {
429 LTy = LTy->getPointerTo();
430 ThrowOnBad = true;
431 }
432
Mike Stump2b35baf2009-11-16 22:52:20 +0000433 CXXRecordDecl *SrcTy;
434 QualType Ty = ArgTy;
435 if (ArgTy.getTypePtr()->isPointerType()
436 || ArgTy.getTypePtr()->isReferenceType())
437 Ty = Ty.getTypePtr()->getPointeeType();
438 CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
439 Ty = CanTy.getUnqualifiedType();
440 SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
Mike Stumpc849c052009-11-16 06:50:58 +0000441
Mike Stumpc849c052009-11-16 06:50:58 +0000442 llvm::BasicBlock *ContBlock = createBasicBlock();
443 llvm::BasicBlock *NullBlock = 0;
444 llvm::BasicBlock *NonZeroBlock = 0;
445 if (CanBeZero) {
446 NonZeroBlock = createBasicBlock();
447 NullBlock = createBasicBlock();
448 llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy);
449 Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
450 NonZeroBlock, NullBlock);
451 EmitBlock(NonZeroBlock);
452 }
453
Mike Stumpc849c052009-11-16 06:50:58 +0000454 llvm::BasicBlock *BadCastBlock = 0;
Mike Stumpc849c052009-11-16 06:50:58 +0000455
Mike Stump2b35baf2009-11-16 22:52:20 +0000456 const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType());
457
458 // See if this is a dynamic_cast(void*)
459 if (ToVoid) {
460 llvm::Value *This = V;
461 V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo());
462 V = Builder.CreateLoad(V, "vtable");
463 V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL);
464 V = Builder.CreateLoad(V, "offset to top");
465 This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext));
466 V = Builder.CreateInBoundsGEP(This, V);
467 V = Builder.CreateBitCast(V, LTy);
468 } else {
469 /// Call __dynamic_cast
470 const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
471 const llvm::FunctionType *FTy;
472 std::vector<const llvm::Type*> ArgTys;
473 const llvm::Type *PtrToInt8Ty
474 = llvm::Type::getInt8Ty(VMContext)->getPointerTo();
475 ArgTys.push_back(PtrToInt8Ty);
476 ArgTys.push_back(PtrToInt8Ty);
477 ArgTys.push_back(PtrToInt8Ty);
478 ArgTys.push_back(PtrDiffTy);
479 FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
480 CXXRecordDecl *DstTy;
481 Ty = CastTy.getTypePtr()->getPointeeType();
482 CanTy = CGM.getContext().getCanonicalType(Ty);
483 Ty = CanTy.getUnqualifiedType();
484 DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
485
486 // FIXME: Calculate better hint.
487 llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
488 llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy);
489 llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy);
490 V = Builder.CreateBitCast(V, PtrToInt8Ty);
491 V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
492 V, SrcArg, DstArg, hint);
493 V = Builder.CreateBitCast(V, LTy);
494
495 if (ThrowOnBad) {
496 BadCastBlock = createBasicBlock();
497
498 llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
499 Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
500 ContBlock, BadCastBlock);
501 EmitBlock(BadCastBlock);
502 /// Call __cxa_bad_cast
503 ResultType = llvm::Type::getVoidTy(VMContext);
504 const llvm::FunctionType *FBadTy;
Mike Stumpfde17be2009-11-17 03:01:03 +0000505 FBadTy = llvm::FunctionType::get(ResultType, false);
Mike Stump2b35baf2009-11-16 22:52:20 +0000506 llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
507 Builder.CreateCall(F)->setDoesNotReturn();
Mike Stump8b152b82009-11-17 00:08:50 +0000508 Builder.CreateUnreachable();
Mike Stump2b35baf2009-11-16 22:52:20 +0000509 }
Mike Stumpc849c052009-11-16 06:50:58 +0000510 }
511
512 if (CanBeZero) {
513 Builder.CreateBr(ContBlock);
514 EmitBlock(NullBlock);
515 Builder.CreateBr(ContBlock);
516 }
517 EmitBlock(ContBlock);
518 if (CanBeZero) {
519 llvm::PHINode *PHI = Builder.CreatePHI(LTy);
Mike Stump14431c12009-11-17 00:10:05 +0000520 PHI->reserveOperandSpace(2);
Mike Stumpc849c052009-11-16 06:50:58 +0000521 PHI->addIncoming(V, NonZeroBlock);
522 PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
Mike Stumpc849c052009-11-16 06:50:58 +0000523 V = PHI;
524 }
525
526 return V;
527}