[cfe-commits] r88901 - in /cfe/trunk/lib/CodeGen: CGCXXExpr.cpp CGExpr.cpp CGExprScalar.cpp CodeGenFunction.h

Mike Stump mrs at apple.com
Sun Nov 15 22:50:58 PST 2009


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?
         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





More information about the cfe-commits mailing list