[cfe-commits] r88901 - in /cfe/trunk/lib/CodeGen: CGCXXExpr.cpp CGExpr.cpp CGExprScalar.cpp CodeGenFunction.h
Daniel Dunbar
daniel at zuster.org
Mon Nov 16 09:59:51 PST 2009
On Sun, Nov 15, 2009 at 11:50 PM, Mike Stump <mrs at apple.com> wrote:
> Author: mrs
> Date: Mon Nov 16 00:50:58 2009
> New Revision: 88901
>
> URL: http://llvm.org/viewvc/llvm-project?rev=88901&view=rev
> Log:
> Implement most of dynamic_cast. WIP.
>
> Modified:
> cfe/trunk/lib/CodeGen/CGCXXExpr.cpp
> cfe/trunk/lib/CodeGen/CGExpr.cpp
> cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> cfe/trunk/lib/CodeGen/CodeGenFunction.h
>
> Modified: cfe/trunk/lib/CodeGen/CGCXXExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXExpr.cpp?rev=88901&r1=88900&r2=88901&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCXXExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCXXExpr.cpp Mon Nov 16 00:50:58 2009
> @@ -388,7 +388,8 @@
> const llvm::FunctionType *FTy;
> FTy = llvm::FunctionType::get(ResultType, false);
> llvm::Value *F = CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
> - Builder.CreateCall(F);
> + Builder.CreateCall(F)->setDoesNotReturn();
> + // FIXME: Should we have the below?
If this is returning to the create unreachable, yes, calls to noreturn
function should be followed by an unreachable.
- Daniel
> Builder.CreateUnreachable();
> EmitBlock(NonZeroBlock);
> }
> @@ -403,3 +404,111 @@
> ErrorUnsupported(E, "typeid expression");
> return 0;
> }
> +
> +llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *V,
> + const CXXDynamicCastExpr *DCE) {
> + QualType CastTy = DCE->getTypeAsWritten();
> + 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();
> + if (CastTy->isPointerType()) {
> + // FIXME: if PointerType->hasAttr<NonNullAttr>(), we don't set this
> + CanBeZero = true;
> + if (InnerType->isVoidType())
> + ToVoid = true;
> + } else {
> + LTy = LTy->getPointerTo();
> + ThrowOnBad = true;
> + }
> +
> + // FIXME: Add support for ToVoid
> +
> + // FIXME: Ensure non-runtime casts are done before this point.
> +
> + llvm::BasicBlock *ContBlock = createBasicBlock();
> + llvm::BasicBlock *NullBlock = 0;
> + llvm::BasicBlock *NonZeroBlock = 0;
> + if (CanBeZero) {
> + NonZeroBlock = createBasicBlock();
> + NullBlock = createBasicBlock();
> + llvm::Value *Zero = llvm::Constant::getNullValue(LArgTy);
> + Builder.CreateCondBr(Builder.CreateICmpNE(V, Zero),
> + NonZeroBlock, NullBlock);
> + EmitBlock(NonZeroBlock);
> + }
> +
> +
> + /// 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();
> + }
> +
> + if (CanBeZero) {
> + Builder.CreateBr(ContBlock);
> + EmitBlock(NullBlock);
> + Builder.CreateBr(ContBlock);
> + }
> + EmitBlock(ContBlock);
> + if (CanBeZero) {
> + llvm::PHINode *PHI = Builder.CreatePHI(LTy);
> + PHI->reserveOperandSpace(3);
> + PHI->addIncoming(V, NonZeroBlock);
> + PHI->addIncoming(llvm::Constant::getNullValue(LTy), NullBlock);
> + if (ThrowOnBad)
> + PHI->addIncoming(llvm::Constant::getNullValue(LTy), BadCastBlock);
> + V = PHI;
> + }
> +
> + return V;
> +}
>
> Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=88901&r1=88900&r2=88901&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Nov 16 00:50:58 2009
> @@ -1290,16 +1290,26 @@
> return LValue::MakeAddr(Temp, MakeQualifiers(E->getType()));
> }
>
> -/// EmitCastLValue - Casts are never lvalues. If a cast is needed by the code
> -/// generator in an lvalue context, then it must mean that we need the address
> -/// of an aggregate in order to access one of its fields. This can happen for
> -/// all the reasons that casts are permitted with aggregate result, including
> -/// noop aggregate casts, and cast from scalar to union.
> +/// EmitCastLValue - Casts are never lvalues unless that cast is a dynamic_cast.
> +/// If the cast is a dynamic_cast, we can have the usual lvalue result,
> +/// otherwise if a cast is needed by the code generator in an lvalue context,
> +/// then it must mean that we need the address of an aggregate in order to
> +/// access one of its fields. This can happen for all the reasons that casts
> +/// are permitted with aggregate result, including noop aggregate casts, and
> +/// cast from scalar to union.
> LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
> switch (E->getCastKind()) {
> default:
> return EmitUnsupportedLValue(E, "unexpected cast lvalue");
>
> + case CastExpr::CK_Dynamic: {
> + LValue LV = EmitLValue(E->getSubExpr());
> + llvm::Value *V = LV.getAddress();
> + const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(E);
> + return LValue::MakeAddr(EmitDynamicCast(V, DCE),
> + MakeQualifiers(E->getType()));
> + }
> +
> case CastExpr::CK_NoOp:
> case CastExpr::CK_ConstructorConversion:
> case CastExpr::CK_UserDefinedConversion:
>
> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=88901&r1=88900&r2=88901&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Nov 16 00:50:58 2009
> @@ -852,6 +852,12 @@
> Value *Src = Visit(const_cast<Expr*>(E));
> return Builder.CreatePtrToInt(Src, ConvertType(DestTy));
> }
> +
> + case CastExpr::CK_Dynamic: {
> + Value *V = Visit(const_cast<Expr*>(E));
> + const CXXDynamicCastExpr *DCE = cast<CXXDynamicCastExpr>(CE);
> + return CGF.EmitDynamicCast(V, DCE);
> + }
>
> }
>
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=88901&r1=88900&r2=88901&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Mon Nov 16 00:50:58 2009
> @@ -664,6 +664,7 @@
> void EmitCXXDeleteExpr(const CXXDeleteExpr *E);
>
> llvm::Value* EmitCXXTypeidExpr(const CXXTypeidExpr *E);
> + llvm::Value *EmitDynamicCast(llvm::Value *V, const CXXDynamicCastExpr *DCE);
>
> //===--------------------------------------------------------------------===//
> // Declaration Emission
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list