[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