[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