[cfe-commits] r88988 - /cfe/trunk/lib/CodeGen/CGCXXExpr.cpp
Mike Stump
mrs at apple.com
Mon Nov 16 14:52:20 PST 2009
Author: mrs
Date: Mon Nov 16 16:52:20 2009
New Revision: 88988
URL: http://llvm.org/viewvc/llvm-project?rev=88988&view=rev
Log:
Implement dynamic_cast<void*>(E).
Modified:
cfe/trunk/lib/CodeGen/CGCXXExpr.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXXExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXExpr.cpp?rev=88988&r1=88987&r2=88988&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXXExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXXExpr.cpp Mon Nov 16 16:52:20 2009
@@ -408,26 +408,14 @@
llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
const CXXDynamicCastExpr *DCE) {
QualType CastTy = DCE->getTypeAsWritten();
+ QualType InnerType = CastTy->getPointeeType();
QualType ArgTy = DCE->getSubExpr()->getType();
const llvm::Type *LArgTy = ConvertType(ArgTy);
const llvm::Type *LTy = ConvertType(DCE->getType());
- CXXRecordDecl *SrcTy;
- CXXRecordDecl *DstTy;
- QualType Ty = CastTy.getTypePtr()->getPointeeType();
- CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
- Ty = CanTy.getUnqualifiedType();
- DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
- Ty = ArgTy;
- if (ArgTy.getTypePtr()->isPointerType()
- || ArgTy.getTypePtr()->isReferenceType())
- Ty = Ty.getTypePtr()->getPointeeType();
- CanTy = CGM.getContext().getCanonicalType(Ty);
- Ty = CanTy.getUnqualifiedType();
- SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
+
bool CanBeZero = false;
- bool ThrowOnBad = false;
bool ToVoid = false;
- QualType InnerType = CastTy->getPointeeType();
+ bool ThrowOnBad = false;
if (CastTy->isPointerType()) {
// FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
CanBeZero = true;
@@ -438,7 +426,14 @@
ThrowOnBad = true;
}
- // FIXME: Add support for ToVoid
+ CXXRecordDecl *SrcTy;
+ QualType Ty = ArgTy;
+ if (ArgTy.getTypePtr()->isPointerType()
+ || ArgTy.getTypePtr()->isReferenceType())
+ Ty = Ty.getTypePtr()->getPointeeType();
+ CanQualType CanTy = CGM.getContext().getCanonicalType(Ty);
+ Ty = CanTy.getUnqualifiedType();
+ SrcTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
llvm::BasicBlock *ContBlock = createBasicBlock();
llvm::BasicBlock *NullBlock = 0;
@@ -452,44 +447,62 @@
EmitBlock(NonZeroBlock);
}
+ llvm::BasicBlock *BadCastBlock = 0;
- /// Call __dynamic_cast
- const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
- const llvm::FunctionType *FTy;
- std::vector<const llvm::Type*> ArgTys;
- const llvm::Type *PtrToInt8Ty
- = llvm::Type::getInt8Ty(VMContext)->getPointerTo();
const llvm::Type *PtrDiffTy = ConvertType(getContext().getSizeType());
- ArgTys.push_back(PtrToInt8Ty);
- ArgTys.push_back(PtrToInt8Ty);
- ArgTys.push_back(PtrToInt8Ty);
- ArgTys.push_back(PtrDiffTy);
- FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
-
- // FIXME: Calculate better hint.
- llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
- llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy);
- llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy);
- V = Builder.CreateBitCast(V, PtrToInt8Ty);
- V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
- V, SrcArg, DstArg, hint);
- V = Builder.CreateBitCast(V, LTy);
-
- llvm::BasicBlock *BadCastBlock = 0;
- if (ThrowOnBad) {
- BadCastBlock = createBasicBlock();
- llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
- Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
- ContBlock, BadCastBlock);
- EmitBlock(BadCastBlock);
- /// Call __cxa_bad_cast
- ResultType = llvm::Type::getVoidTy(VMContext);
- const llvm::FunctionType *FBadTy;
- FTy = llvm::FunctionType::get(ResultType, false);
- llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
- Builder.CreateCall(F)->setDoesNotReturn();
- // Builder.CreateUnreachable();
+ // See if this is a dynamic_cast(void*)
+ if (ToVoid) {
+ llvm::Value *This = V;
+ V = Builder.CreateBitCast(This, PtrDiffTy->getPointerTo()->getPointerTo());
+ V = Builder.CreateLoad(V, "vtable");
+ V = Builder.CreateConstInBoundsGEP1_64(V, -2ULL);
+ V = Builder.CreateLoad(V, "offset to top");
+ This = Builder.CreateBitCast(This, llvm::Type::getInt8PtrTy(VMContext));
+ V = Builder.CreateInBoundsGEP(This, V);
+ V = Builder.CreateBitCast(V, LTy);
+ } else {
+ /// Call __dynamic_cast
+ const llvm::Type *ResultType = llvm::Type::getInt8PtrTy(VMContext);
+ const llvm::FunctionType *FTy;
+ std::vector<const llvm::Type*> ArgTys;
+ const llvm::Type *PtrToInt8Ty
+ = llvm::Type::getInt8Ty(VMContext)->getPointerTo();
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(PtrToInt8Ty);
+ ArgTys.push_back(PtrDiffTy);
+ FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
+ CXXRecordDecl *DstTy;
+ Ty = CastTy.getTypePtr()->getPointeeType();
+ CanTy = CGM.getContext().getCanonicalType(Ty);
+ Ty = CanTy.getUnqualifiedType();
+ DstTy = cast<CXXRecordDecl>(Ty->getAs<RecordType>()->getDecl());
+
+ // FIXME: Calculate better hint.
+ llvm::Value *hint = llvm::ConstantInt::get(PtrDiffTy, -1ULL);
+ llvm::Value *SrcArg = CGM.GenerateRttiRef(SrcTy);
+ llvm::Value *DstArg = CGM.GenerateRttiRef(DstTy);
+ V = Builder.CreateBitCast(V, PtrToInt8Ty);
+ V = Builder.CreateCall4(CGM.CreateRuntimeFunction(FTy, "__dynamic_cast"),
+ V, SrcArg, DstArg, hint);
+ V = Builder.CreateBitCast(V, LTy);
+
+ if (ThrowOnBad) {
+ BadCastBlock = createBasicBlock();
+
+ llvm::Value *Zero = llvm::Constant::getNullValue(LTy);
+ Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
+ ContBlock, BadCastBlock);
+ EmitBlock(BadCastBlock);
+ /// Call __cxa_bad_cast
+ ResultType = llvm::Type::getVoidTy(VMContext);
+ const llvm::FunctionType *FBadTy;
+ FTy = llvm::FunctionType::get(ResultType, false);
+ llvm::Value *F = CGM.CreateRuntimeFunction(FBadTy, "__cxa_bad_cast");
+ Builder.CreateCall(F)->setDoesNotReturn();
+ // Builder.CreateUnreachable();
+ }
}
if (CanBeZero) {
More information about the cfe-commits
mailing list