r211473 - Revert "Revert r211402 (and r211408, r211410), "CodeGen: Refactor dynamic_cast and typeid" It crashes msvc codegen in clang/test/SemaCXX/undefined-internal.cpp."

David Majnemer david.majnemer at gmail.com
Sun Jun 22 14:39:58 PDT 2014


Below is a reconstruction of the delta between the original commit,
r211402, and the ultimate commit, r211473.

The difference boiled down to whether or not the adjusted 'this' pointer
was calculated via getPolymorphicOffset or performBaseAdjustment.
 getPolymorphicOffset assumes that there is some base in the most derived
type which is polymorphic while performBaseAdjustment first checks to see
if the most derived type has it's own virtual function-table pointer.

$ git diff a73161..5d2297 lib/CodeGen
diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp
b/lib/CodeGen/MicrosoftCXXABI.cpp
index f3c79ef..e19904f 100644
--- a/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -548,10 +548,13 @@ llvm::Value
*MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
                                          QualType SrcRecordTy,
                                          llvm::Value *ThisPtr,
                                          llvm::Type *StdTypeInfoPtrTy) {
-  llvm::Value *Offset;
-  std::tie(ThisPtr, Offset) = performBaseAdjustment(CGF, ThisPtr,
SrcRecordTy);
+  const CXXRecordDecl *RD = SrcRecordTy->getAsCXXRecordDecl();
+  llvm::Value *CastPtr = CGF.Builder.CreateBitCast(ThisPtr, CGF.Int8PtrTy);
+  llvm::Value *AdjustedThisPtr = CGF.Builder.CreateInBoundsGEP(
+      CastPtr, getPolymorphicOffset(CGF, RD, CastPtr));
   return CGF.Builder.CreateBitCast(
-      emitRTtypeidCall(CGF, ThisPtr).getInstruction(), StdTypeInfoPtrTy);
+      emitRTtypeidCall(CGF, AdjustedThisPtr).getInstruction(),
+      StdTypeInfoPtrTy);
 }

 bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,


On Sun, Jun 22, 2014 at 8:59 PM, David Blaikie <dblaikie at gmail.com> wrote:

> I'm a little confused about what was reverted/committed here. If this was
> a recommit after a revert due to breakage it'd be nice to understand how
> the breakage was addressed, for example.
> On Jun 22, 2014 12:19 PM, "David Majnemer" <david.majnemer at gmail.com>
> wrote:
>
>> Author: majnemer
>> Date: Sun Jun 22 14:05:33 2014
>> New Revision: 211473
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=211473&view=rev
>> Log:
>> Revert "Revert r211402 (and r211408,r211410), "CodeGen: Refactor
>> dynamic_cast and typeid" It crashes msvc codegen in
>> clang/test/SemaCXX/undefined-internal.cpp."
>>
>> This reverts commit r211467 which reverted r211408,r211410, it caused
>> crashes in test/SemaCXX/undefined-internal.cpp for i686-win32 targets.
>>
>> Modified:
>>     cfe/trunk/lib/CodeGen/CGCXXABI.h
>>     cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>>     cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>>     cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>>     cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
>>     cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp
>>
>> Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=211473&r1=211472&r2=211473&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
>> +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Sun Jun 22 14:05:33 2014
>> @@ -207,6 +207,28 @@ public:
>>                                                llvm::Value *ptr,
>>                                                QualType type) = 0;
>>
>> +  virtual bool shouldTypeidBeNullChecked(bool IsDeref,
>> +                                         QualType SrcRecordTy) = 0;
>> +  virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0;
>> +  virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType
>> SrcRecordTy,
>> +                                  llvm::Value *ThisPtr,
>> +                                  llvm::Type *StdTypeInfoPtrTy) = 0;
>> +
>> +  virtual bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
>> +                                                  QualType SrcRecordTy)
>> = 0;
>> +
>> +  virtual llvm::Value *
>> +  EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
>> +                      QualType SrcRecordTy, QualType DestTy,
>> +                      QualType DestRecordTy, llvm::BasicBlock *CastEnd)
>> = 0;
>> +
>> +  virtual llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF,
>> +                                             llvm::Value *Value,
>> +                                             QualType SrcRecordTy,
>> +                                             QualType DestTy) = 0;
>> +
>> +  virtual bool EmitBadCastCall(CodeGenFunction &CGF) = 0;
>> +
>>    virtual llvm::Value *GetVirtualBaseClassOffset(CodeGenFunction &CGF,
>>                                                   llvm::Value *This,
>>                                                   const CXXRecordDecl
>> *ClassDecl,
>>
>> Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=211473&r1=211472&r2=211473&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun Jun 22 14:05:33 2014
>> @@ -1615,98 +1615,36 @@ void CodeGenFunction::EmitCXXDeleteExpr(
>>    EmitBlock(DeleteEnd);
>>  }
>>
>> -static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) {
>> -  // void __cxa_bad_typeid();
>> -  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
>> -
>> -  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
>> -}
>> -
>> -static void EmitBadTypeidCall(CodeGenFunction &CGF) {
>> -  llvm::Value *Fn = getBadTypeidFn(CGF);
>> -  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
>> -  CGF.Builder.CreateUnreachable();
>> -}
>> -
>> -/// \brief Gets the offset to the virtual base that contains the vfptr
>> for
>> -/// MS-ABI polymorphic types.
>> -static llvm::Value *getPolymorphicOffset(CodeGenFunction &CGF,
>> -                                         const CXXRecordDecl *RD,
>> -                                         llvm::Value *Value) {
>> -  const ASTContext &Context = RD->getASTContext();
>> -  for (const CXXBaseSpecifier &Base : RD->vbases())
>> -    if (Context.getASTRecordLayout(Base.getType()->getAsCXXRecordDecl())
>> -            .hasExtendableVFPtr())
>> -      return CGF.CGM.getCXXABI().GetVirtualBaseClassOffset(
>> -          CGF, Value, RD, Base.getType()->getAsCXXRecordDecl());
>> -  llvm_unreachable("One of our vbases should be polymorphic.");
>> -}
>> -
>> -static llvm::Value *emitRTtypeidCall(CodeGenFunction &CGF,
>> -                                     llvm::Value *Argument) {
>> -  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
>> -  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
>> -      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
>> "__RTtypeid");
>> -  llvm::Value *Args[] = {Argument};
>> -  return CGF.EmitRuntimeCall(Function, Args);
>> -}
>> -
>>  static llvm::Value *EmitTypeidFromVTable(CodeGenFunction &CGF, const
>> Expr *E,
>>                                           llvm::Type *StdTypeInfoPtrTy) {
>>    // Get the vtable pointer.
>>    llvm::Value *ThisPtr = CGF.EmitLValue(E).getAddress();
>>
>> -  if (CGF.getTarget().getCXXABI().isMicrosoft()) {
>> -    llvm::Value *CastPtr = CGF.Builder.CreateBitCast(ThisPtr,
>> CGF.Int8PtrTy);
>> -    const CXXRecordDecl *RD = E->getType()->getAsCXXRecordDecl();
>> -    if (CGF.getContext().getASTRecordLayout(RD).hasExtendableVFPtr())
>> -      return CGF.Builder.CreateBitCast(emitRTtypeidCall(CGF, CastPtr),
>> -                                       StdTypeInfoPtrTy);
>> -    llvm::BasicBlock *EntryBlock = CGF.Builder.GetInsertBlock();
>> -    llvm::BasicBlock *AdjustBlock =
>> CGF.createBasicBlock("type_id.valid");
>> -    llvm::BasicBlock *ExitBlock = CGF.createBasicBlock("type_id.call");
>> -    CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNull(CastPtr),
>> ExitBlock,
>> -                             AdjustBlock);
>> -    // Emit the call block and code for it.
>> -    CGF.EmitBlock(AdjustBlock);
>> -    llvm::Value *AdjustedThisPtr = CGF.Builder.CreateInBoundsGEP(
>> -        CastPtr, getPolymorphicOffset(CGF, RD, CastPtr));
>> -    // Emit the call block and the phi nodes for it.
>> -    CGF.EmitBlock(ExitBlock);
>> -    llvm::PHINode *ValuePHI = CGF.Builder.CreatePHI(CGF.Int8PtrTy, 2);
>> -    ValuePHI->addIncoming(AdjustedThisPtr, AdjustBlock);
>> -    ValuePHI->addIncoming(llvm::Constant::getNullValue(CGF.Int8PtrTy),
>> -                          EntryBlock);
>> -    return CGF.Builder.CreateBitCast(emitRTtypeidCall(CGF, ValuePHI),
>> -                                     StdTypeInfoPtrTy);
>> -  }
>> -
>>    // C++ [expr.typeid]p2:
>>    //   If the glvalue expression is obtained by applying the unary *
>> operator to
>>    //   a pointer and the pointer is a null pointer value, the typeid
>> expression
>>    //   throws the std::bad_typeid exception.
>> -  if (const UnaryOperator *UO =
>> dyn_cast<UnaryOperator>(E->IgnoreParens())) {
>> -    if (UO->getOpcode() == UO_Deref) {
>> -      llvm::BasicBlock *BadTypeidBlock =
>> +  bool IsDeref = false;
>> +  if (const UnaryOperator *UO =
>> dyn_cast<UnaryOperator>(E->IgnoreParens()))
>> +    if (UO->getOpcode() == UO_Deref)
>> +      IsDeref = true;
>> +
>> +  QualType SrcRecordTy = E->getType();
>> +  if (CGF.CGM.getCXXABI().shouldTypeidBeNullChecked(IsDeref,
>> SrcRecordTy)) {
>> +    llvm::BasicBlock *BadTypeidBlock =
>>          CGF.createBasicBlock("typeid.bad_typeid");
>> -      llvm::BasicBlock *EndBlock =
>> -        CGF.createBasicBlock("typeid.end");
>> +    llvm::BasicBlock *EndBlock = CGF.createBasicBlock("typeid.end");
>>
>> -      llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr);
>> -      CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
>> +    llvm::Value *IsNull = CGF.Builder.CreateIsNull(ThisPtr);
>> +    CGF.Builder.CreateCondBr(IsNull, BadTypeidBlock, EndBlock);
>>
>> -      CGF.EmitBlock(BadTypeidBlock);
>> -      EmitBadTypeidCall(CGF);
>> -      CGF.EmitBlock(EndBlock);
>> -    }
>> +    CGF.EmitBlock(BadTypeidBlock);
>> +    CGF.CGM.getCXXABI().EmitBadTypeidCall(CGF);
>> +    CGF.EmitBlock(EndBlock);
>>    }
>>
>> -  llvm::Value *Value = CGF.GetVTablePtr(ThisPtr,
>> -
>>  StdTypeInfoPtrTy->getPointerTo());
>> -
>> -  // Load the type info.
>> -  Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
>> -  return CGF.Builder.CreateLoad(Value);
>> +  return CGF.CGM.getCXXABI().EmitTypeid(CGF, SrcRecordTy, ThisPtr,
>> +                                        StdTypeInfoPtrTy);
>>  }
>>
>>  llvm::Value *CodeGenFunction::EmitCXXTypeidExpr(const CXXTypeidExpr *E) {
>> @@ -1733,173 +1671,6 @@ llvm::Value *CodeGenFunction::EmitCXXTyp
>>                                 StdTypeInfoPtrTy);
>>  }
>>
>> -static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
>> -  // void *__dynamic_cast(const void *sub,
>> -  //                      const abi::__class_type_info *src,
>> -  //                      const abi::__class_type_info *dst,
>> -  //                      std::ptrdiff_t src2dst_offset);
>> -
>> -  llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
>> -  llvm::Type *PtrDiffTy =
>> -    CGF.ConvertType(CGF.getContext().getPointerDiffType());
>> -
>> -  llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
>> -
>> -  llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
>> false);
>> -
>> -  // Mark the function as nounwind readonly.
>> -  llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind,
>> -                                            llvm::Attribute::ReadOnly };
>> -  llvm::AttributeSet Attrs = llvm::AttributeSet::get(
>> -      CGF.getLLVMContext(), llvm::AttributeSet::FunctionIndex,
>> FuncAttrs);
>> -
>> -  return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
>> -}
>> -
>> -static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
>> -  // void __cxa_bad_cast();
>> -  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
>> -  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
>> -}
>> -
>> -static void EmitBadCastCall(CodeGenFunction &CGF) {
>> -  llvm::Value *Fn = getBadCastFn(CGF);
>> -  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
>> -  CGF.Builder.CreateUnreachable();
>> -}
>> -
>> -/// \brief Compute the src2dst_offset hint as described in the
>> -/// Itanium C++ ABI [2.9.7]
>> -static CharUnits computeOffsetHint(ASTContext &Context,
>> -                                   const CXXRecordDecl *Src,
>> -                                   const CXXRecordDecl *Dst) {
>> -  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
>> -                     /*DetectVirtual=*/false);
>> -
>> -  // If Dst is not derived from Src we can skip the whole computation
>> below and
>> -  // return that Src is not a public base of Dst.  Record all
>> inheritance paths.
>> -  if (!Dst->isDerivedFrom(Src, Paths))
>> -    return CharUnits::fromQuantity(-2ULL);
>> -
>> -  unsigned NumPublicPaths = 0;
>> -  CharUnits Offset;
>> -
>> -  // Now walk all possible inheritance paths.
>> -  for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end();
>> -       I != E; ++I) {
>> -    if (I->Access != AS_public) // Ignore non-public inheritance.
>> -      continue;
>> -
>> -    ++NumPublicPaths;
>> -
>> -    for (CXXBasePath::iterator J = I->begin(), JE = I->end(); J != JE;
>> ++J) {
>> -      // If the path contains a virtual base class we can't give any
>> hint.
>> -      // -1: no hint.
>> -      if (J->Base->isVirtual())
>> -        return CharUnits::fromQuantity(-1ULL);
>> -
>> -      if (NumPublicPaths > 1) // Won't use offsets, skip computation.
>> -        continue;
>> -
>> -      // Accumulate the base class offsets.
>> -      const ASTRecordLayout &L = Context.getASTRecordLayout(J->Class);
>> -      Offset +=
>> L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
>> -    }
>> -  }
>> -
>> -  // -2: Src is not a public base of Dst.
>> -  if (NumPublicPaths == 0)
>> -    return CharUnits::fromQuantity(-2ULL);
>> -
>> -  // -3: Src is a multiple public base type but never a virtual base
>> type.
>> -  if (NumPublicPaths > 1)
>> -    return CharUnits::fromQuantity(-3ULL);
>> -
>> -  // Otherwise, the Src type is a unique public nonvirtual base type of
>> Dst.
>> -  // Return the offset of Src from the origin of Dst.
>> -  return Offset;
>> -}
>> -
>> -static llvm::Value *
>> -EmitItaniumDynamicCastCall(CodeGenFunction &CGF, llvm::Value *Value,
>> -                    QualType SrcTy, QualType DestTy,
>> -                    llvm::BasicBlock *CastEnd) {
>> -  llvm::Type *PtrDiffLTy =
>> -    CGF.ConvertType(CGF.getContext().getPointerDiffType());
>> -  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
>> -
>> -  if (const PointerType *PTy = DestTy->getAs<PointerType>()) {
>> -    if (PTy->getPointeeType()->isVoidType()) {
>> -      // C++ [expr.dynamic.cast]p7:
>> -      //   If T is "pointer to cv void," then the result is a pointer to
>> the
>> -      //   most derived object pointed to by v.
>> -
>> -      // Get the vtable pointer.
>> -      llvm::Value *VTable = CGF.GetVTablePtr(Value,
>> PtrDiffLTy->getPointerTo());
>> -
>> -      // Get the offset-to-top from the vtable.
>> -      llvm::Value *OffsetToTop =
>> -        CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
>> -      OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop, "offset.to.top");
>> -
>> -      // Finally, add the offset to the pointer.
>> -      Value = CGF.EmitCastToVoidPtr(Value);
>> -      Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
>> -
>> -      return CGF.Builder.CreateBitCast(Value, DestLTy);
>> -    }
>> -  }
>> -
>> -  QualType SrcRecordTy;
>> -  QualType DestRecordTy;
>> -
>> -  if (const PointerType *DestPTy = DestTy->getAs<PointerType>()) {
>> -    SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType();
>> -    DestRecordTy = DestPTy->getPointeeType();
>> -  } else {
>> -    SrcRecordTy = SrcTy;
>> -    DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType();
>> -  }
>> -
>> -  assert(SrcRecordTy->isRecordType() && "source type must be a record
>> type!");
>> -  assert(DestRecordTy->isRecordType() && "dest type must be a record
>> type!");
>> -
>> -  llvm::Value *SrcRTTI =
>> -    CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
>> -  llvm::Value *DestRTTI =
>> -    CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
>> -
>> -  // Compute the offset hint.
>> -  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
>> -  const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
>> -  llvm::Value *OffsetHint =
>> -    llvm::ConstantInt::get(PtrDiffLTy,
>> -                           computeOffsetHint(CGF.getContext(), SrcDecl,
>> -                                             DestDecl).getQuantity());
>> -
>> -  // Emit the call to __dynamic_cast.
>> -  Value = CGF.EmitCastToVoidPtr(Value);
>> -
>> -  llvm::Value *args[] = { Value, SrcRTTI, DestRTTI, OffsetHint };
>> -  Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF),
>> args);
>> -  Value = CGF.Builder.CreateBitCast(Value, DestLTy);
>> -
>> -  /// C++ [expr.dynamic.cast]p9:
>> -  ///   A failed cast to reference type throws std::bad_cast
>> -  if (DestTy->isReferenceType()) {
>> -    llvm::BasicBlock *BadCastBlock =
>> -      CGF.createBasicBlock("dynamic_cast.bad_cast");
>> -
>> -    llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
>> -    CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
>> -
>> -    CGF.EmitBlock(BadCastBlock);
>> -    EmitBadCastCall(CGF);
>> -  }
>> -
>> -  return Value;
>> -}
>> -
>>  static llvm::Value *EmitDynamicCastToNull(CodeGenFunction &CGF,
>>                                            QualType DestTy) {
>>    llvm::Type *DestLTy = CGF.ConvertType(DestTy);
>> @@ -1908,142 +1679,49 @@ static llvm::Value *EmitDynamicCastToNul
>>
>>    /// C++ [expr.dynamic.cast]p9:
>>    ///   A failed cast to reference type throws std::bad_cast
>> -  EmitBadCastCall(CGF);
>> +  if (!CGF.CGM.getCXXABI().EmitBadCastCall(CGF))
>> +    return nullptr;
>>
>>    CGF.EmitBlock(CGF.createBasicBlock("dynamic_cast.end"));
>>    return llvm::UndefValue::get(DestLTy);
>>  }
>>
>> -namespace {
>> -struct MSDynamicCastBuilder {
>> -  MSDynamicCastBuilder(CodeGenFunction &CGF, const CXXDynamicCastExpr
>> *DCE);
>> -  llvm::Value *emitDynamicCastCall(llvm::Value *Value);
>> -  llvm::Value *emitDynamicCast(llvm::Value *Value);
>> -
>> -  CodeGenFunction &CGF;
>> -  CGBuilderTy &Builder;
>> -  llvm::PointerType *Int8PtrTy;
>> -  QualType SrcTy, DstTy;
>> -  const CXXRecordDecl *SrcDecl;
>> -  bool IsPtrCast, IsCastToVoid, IsCastOfNull;
>> -};
>> -} // namespace
>> -
>> -MSDynamicCastBuilder::MSDynamicCastBuilder(CodeGenFunction &CGF,
>> -                                           const CXXDynamicCastExpr *DCE)
>> -    : CGF(CGF), Builder(CGF.Builder), Int8PtrTy(CGF.Int8PtrTy),
>> -      SrcDecl(nullptr) {
>> -  DstTy = DCE->getTypeAsWritten();
>> -  IsPtrCast = DstTy->isPointerType();
>> -  // Get the PointeeTypes.  After this point the original types are not
>> used.
>> -  DstTy = IsPtrCast ? DstTy->castAs<PointerType>()->getPointeeType()
>> -                    : DstTy->castAs<ReferenceType>()->getPointeeType();
>> -  IsCastToVoid = DstTy->isVoidType();
>> -  IsCastOfNull = DCE->isAlwaysNull();
>> -  if (IsCastOfNull)
>> -    return;
>> -  SrcTy = DCE->getSubExpr()->getType();
>> -  SrcTy = IsPtrCast ? SrcTy->castAs<PointerType>()->getPointeeType() :
>> SrcTy;
>> -  SrcDecl = SrcTy->getAsCXXRecordDecl();
>> -  // If we don't need a base adjustment, we don't need a SrcDecl so
>> clear it
>> -  // here.  Later we use the existence of the SrcDecl to determine the
>> need for
>> -  // a base adjustment.
>> -  if (CGF.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
>> -    SrcDecl = nullptr;
>> -}
>> -
>> -llvm::Value *MSDynamicCastBuilder::emitDynamicCastCall(llvm::Value
>> *Value) {
>> -  llvm::IntegerType *Int32Ty = CGF.Int32Ty;
>> -  llvm::Value *Offset = llvm::ConstantInt::get(Int32Ty, 0);
>> -  Value = Builder.CreateBitCast(Value, Int8PtrTy);
>> -  // If we need to perform a base adjustment, do it here.
>> -  if (SrcDecl) {
>> -    Offset = getPolymorphicOffset(CGF, SrcDecl, Value);
>> -    Value = Builder.CreateInBoundsGEP(Value, Offset);
>> -    Offset = Builder.CreateTrunc(Offset, Int32Ty);
>> -  }
>> -  if (IsCastToVoid) {
>> -    // PVOID __RTCastToVoid(
>> -    //   PVOID inptr)
>> -    llvm::Type *ArgTypes[] = {Int8PtrTy};
>> -    llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
>> -        llvm::FunctionType::get(Int8PtrTy, ArgTypes, false),
>> "__RTCastToVoid");
>> -    llvm::Value *Args[] = {Value};
>> -    return CGF.EmitRuntimeCall(Function, Args);
>> -  }
>> -  // PVOID __RTDynamicCast(
>> -  //   PVOID inptr,
>> -  //   LONG VfDelta,
>> -  //   PVOID SrcType,
>> -  //   PVOID TargetType,
>> -  //   BOOL isReference)
>> -  llvm::Type *ArgTypes[] = {Int8PtrTy, Int32Ty, Int8PtrTy, Int8PtrTy,
>> Int32Ty};
>> -  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
>> -      llvm::FunctionType::get(Int8PtrTy, ArgTypes, false),
>> "__RTDynamicCast");
>> -  llvm::Value *Args[] = {
>> -    Value, Offset,
>> -      CGF.CGM.GetAddrOfRTTIDescriptor(SrcTy.getUnqualifiedType()),
>> -      CGF.CGM.GetAddrOfRTTIDescriptor(DstTy.getUnqualifiedType()),
>> -      llvm::ConstantInt::get(Int32Ty, IsPtrCast ? 0 : 1)};
>> -  return CGF.EmitRuntimeCall(Function, Args);
>> -}
>> -
>> -llvm::Value *MSDynamicCastBuilder::emitDynamicCast(llvm::Value *Value) {
>> -  // Note about undefined behavior: If the dynamic cast is casting to a
>> -  // reference type and the input is null, we hit a grey area in the
>> standard.
>> -  // Here we're interpreting the behavior as undefined.  The effects are
>> the
>> -  // following:  If the compiler determines that the argument is
>> statically null
>> -  // or if the argument is dynamically null but does not require base
>> -  // adjustment, __RTDynamicCast will be called with a null argument and
>> the
>> -  // isreference bit set.  In this case __RTDynamicCast will throw
>> -  // std::bad_cast. If the argument is dynamically null and a base
>> adjustment is
>> -  // required the resulting code will produce an out of bounds memory
>> reference
>> -  // when trying to read VBTblPtr.  In Itanium mode clang also emits a
>> vtable
>> -  // load that fails at run time.
>> -  llvm::PointerType *DstLTy = CGF.ConvertType(DstTy)->getPointerTo();
>> -  if (IsCastOfNull && IsPtrCast)
>> -    return Builder.CreateBitCast(Value, DstLTy);
>> -  if (IsCastOfNull || !IsPtrCast || !SrcDecl)
>> -    return Builder.CreateBitCast(emitDynamicCastCall(Value), DstLTy);
>> -  // !IsCastOfNull && IsPtrCast && SrcDecl
>> -  // In this case we have a pointer that requires a base adjustment.  An
>> -  // adjustment is only required if the pointer is actually valid so
>> here we
>> -  // perform a null check before doing the base adjustment and calling
>> -  // __RTDynamicCast.  In the case that the argument is null we simply
>> return
>> -  // null without calling __RTDynamicCast.
>> -  llvm::BasicBlock *EntryBlock = Builder.GetInsertBlock();
>> -  llvm::BasicBlock *CallBlock =
>> CGF.createBasicBlock("dynamic_cast.valid");
>> -  llvm::BasicBlock *ExitBlock =
>> CGF.createBasicBlock("dynamic_cast.call");
>> -  Builder.CreateCondBr(Builder.CreateIsNull(Value), ExitBlock,
>> CallBlock);
>> -  // Emit the call block and code for it.
>> -  CGF.EmitBlock(CallBlock);
>> -  Value = emitDynamicCastCall(Value);
>> -  // Emit the call block and the phi nodes for it.
>> -  CGF.EmitBlock(ExitBlock);
>> -  llvm::PHINode *ValuePHI = Builder.CreatePHI(Int8PtrTy, 2);
>> -  ValuePHI->addIncoming(Value, CallBlock);
>> -  ValuePHI->addIncoming(llvm::Constant::getNullValue(Int8PtrTy),
>> EntryBlock);
>> -  return Builder.CreateBitCast(ValuePHI, DstLTy);
>> -}
>> -
>>  llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
>>                                                const CXXDynamicCastExpr
>> *DCE) {
>> -  if (getTarget().getCXXABI().isMicrosoft()) {
>> -    MSDynamicCastBuilder Builder(*this, DCE);
>> -    return Builder.emitDynamicCast(Value);
>> -  }
>> -
>>    QualType DestTy = DCE->getTypeAsWritten();
>>
>>    if (DCE->isAlwaysNull())
>> -    return EmitDynamicCastToNull(*this, DestTy);
>> +    if (llvm::Value *T = EmitDynamicCastToNull(*this, DestTy))
>> +      return T;
>>
>>    QualType SrcTy = DCE->getSubExpr()->getType();
>>
>> +  // C++ [expr.dynamic.cast]p7:
>> +  //   If T is "pointer to cv void," then the result is a pointer to the
>> most
>> +  //   derived object pointed to by v.
>> +  const PointerType *DestPTy = DestTy->getAs<PointerType>();
>> +
>> +  bool isDynamicCastToVoid;
>> +  QualType SrcRecordTy;
>> +  QualType DestRecordTy;
>> +  if (DestPTy) {
>> +    isDynamicCastToVoid = DestPTy->getPointeeType()->isVoidType();
>> +    SrcRecordTy = SrcTy->castAs<PointerType>()->getPointeeType();
>> +    DestRecordTy = DestPTy->getPointeeType();
>> +  } else {
>> +    isDynamicCastToVoid = false;
>> +    SrcRecordTy = SrcTy;
>> +    DestRecordTy = DestTy->castAs<ReferenceType>()->getPointeeType();
>> +  }
>> +
>> +  assert(SrcRecordTy->isRecordType() && "source type must be a record
>> type!");
>> +
>>    // C++ [expr.dynamic.cast]p4:
>>    //   If the value of v is a null pointer value in the pointer case,
>> the result
>>    //   is the null pointer value of type T.
>> -  bool ShouldNullCheckSrcValue = SrcTy->isPointerType();
>> +  bool ShouldNullCheckSrcValue =
>> +
>>  CGM.getCXXABI().shouldDynamicCastCallBeNullChecked(SrcTy->isPointerType(),
>> +                                                         SrcRecordTy);
>>
>>    llvm::BasicBlock *CastNull = nullptr;
>>    llvm::BasicBlock *CastNotNull = nullptr;
>> @@ -2058,7 +1736,15 @@ llvm::Value *CodeGenFunction::EmitDynami
>>      EmitBlock(CastNotNull);
>>    }
>>
>> -  Value = EmitItaniumDynamicCastCall(*this, Value, SrcTy, DestTy,
>> CastEnd);
>> +  if (isDynamicCastToVoid) {
>> +    Value = CGM.getCXXABI().EmitDynamicCastToVoid(*this, Value,
>> SrcRecordTy,
>> +                                                  DestTy);
>> +  } else {
>> +    assert(DestRecordTy->isRecordType() &&
>> +           "destination type must be a record type!");
>> +    Value = CGM.getCXXABI().EmitDynamicCastCall(*this, Value,
>> SrcRecordTy,
>> +                                                DestTy, DestRecordTy,
>> CastEnd);
>> +  }
>>
>>    if (ShouldNullCheckSrcValue) {
>>      EmitBranch(CastEnd);
>>
>> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=211473&r1=211472&r2=211473&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Sun Jun 22 14:05:33 2014
>> @@ -25,6 +25,7 @@
>>  #include "CodeGenModule.h"
>>  #include "clang/AST/Mangle.h"
>>  #include "clang/AST/Type.h"
>> +#include "llvm/IR/CallSite.h"
>>  #include "llvm/IR/DataLayout.h"
>>  #include "llvm/IR/Intrinsics.h"
>>  #include "llvm/IR/Value.h"
>> @@ -108,6 +109,26 @@ public:
>>    llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF, llvm::Value
>> *ptr,
>>                                        QualType type) override;
>>
>> +  bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy)
>> override;
>> +  void EmitBadTypeidCall(CodeGenFunction &CGF) override;
>> +  llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
>> +                          llvm::Value *ThisPtr,
>> +                          llvm::Type *StdTypeInfoPtrTy) override;
>> +
>> +  bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
>> +                                          QualType SrcRecordTy) override;
>> +
>> +  llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value
>> *Value,
>> +                                   QualType SrcRecordTy, QualType DestTy,
>> +                                   QualType DestRecordTy,
>> +                                   llvm::BasicBlock *CastEnd) override;
>> +
>> +  llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value
>> *Value,
>> +                                     QualType SrcRecordTy,
>> +                                     QualType DestTy) override;
>> +
>> +  bool EmitBadCastCall(CodeGenFunction &CGF) override;
>> +
>>    llvm::Value *
>>      GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
>>                                const CXXRecordDecl *ClassDecl,
>> @@ -800,6 +821,194 @@ llvm::Value *ItaniumCXXABI::adjustToComp
>>    return CGF.Builder.CreateInBoundsGEP(ptr, offset);
>>  }
>>
>> +static llvm::Constant *getItaniumDynamicCastFn(CodeGenFunction &CGF) {
>> +  // void *__dynamic_cast(const void *sub,
>> +  //                      const abi::__class_type_info *src,
>> +  //                      const abi::__class_type_info *dst,
>> +  //                      std::ptrdiff_t src2dst_offset);
>> +
>> +  llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
>> +  llvm::Type *PtrDiffTy =
>> +    CGF.ConvertType(CGF.getContext().getPointerDiffType());
>> +
>> +  llvm::Type *Args[4] = { Int8PtrTy, Int8PtrTy, Int8PtrTy, PtrDiffTy };
>> +
>> +  llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args,
>> false);
>> +
>> +  // Mark the function as nounwind readonly.
>> +  llvm::Attribute::AttrKind FuncAttrs[] = { llvm::Attribute::NoUnwind,
>> +                                            llvm::Attribute::ReadOnly };
>> +  llvm::AttributeSet Attrs = llvm::AttributeSet::get(
>> +      CGF.getLLVMContext(), llvm::AttributeSet::FunctionIndex,
>> FuncAttrs);
>> +
>> +  return CGF.CGM.CreateRuntimeFunction(FTy, "__dynamic_cast", Attrs);
>> +}
>> +
>> +static llvm::Constant *getBadCastFn(CodeGenFunction &CGF) {
>> +  // void __cxa_bad_cast();
>> +  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
>> +  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_cast");
>> +}
>> +
>> +/// \brief Compute the src2dst_offset hint as described in the
>> +/// Itanium C++ ABI [2.9.7]
>> +static CharUnits computeOffsetHint(ASTContext &Context,
>> +                                   const CXXRecordDecl *Src,
>> +                                   const CXXRecordDecl *Dst) {
>> +  CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
>> +                     /*DetectVirtual=*/false);
>> +
>> +  // If Dst is not derived from Src we can skip the whole computation
>> below and
>> +  // return that Src is not a public base of Dst.  Record all
>> inheritance paths.
>> +  if (!Dst->isDerivedFrom(Src, Paths))
>> +    return CharUnits::fromQuantity(-2ULL);
>> +
>> +  unsigned NumPublicPaths = 0;
>> +  CharUnits Offset;
>> +
>> +  // Now walk all possible inheritance paths.
>> +  for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end();
>> I != E;
>> +       ++I) {
>> +    if (I->Access != AS_public) // Ignore non-public inheritance.
>> +      continue;
>> +
>> +    ++NumPublicPaths;
>> +
>> +    for (CXXBasePath::iterator J = I->begin(), JE = I->end(); J != JE;
>> ++J) {
>> +      // If the path contains a virtual base class we can't give any
>> hint.
>> +      // -1: no hint.
>> +      if (J->Base->isVirtual())
>> +        return CharUnits::fromQuantity(-1ULL);
>> +
>> +      if (NumPublicPaths > 1) // Won't use offsets, skip computation.
>> +        continue;
>> +
>> +      // Accumulate the base class offsets.
>> +      const ASTRecordLayout &L = Context.getASTRecordLayout(J->Class);
>> +      Offset +=
>> L.getBaseClassOffset(J->Base->getType()->getAsCXXRecordDecl());
>> +    }
>> +  }
>> +
>> +  // -2: Src is not a public base of Dst.
>> +  if (NumPublicPaths == 0)
>> +    return CharUnits::fromQuantity(-2ULL);
>> +
>> +  // -3: Src is a multiple public base type but never a virtual base
>> type.
>> +  if (NumPublicPaths > 1)
>> +    return CharUnits::fromQuantity(-3ULL);
>> +
>> +  // Otherwise, the Src type is a unique public nonvirtual base type of
>> Dst.
>> +  // Return the offset of Src from the origin of Dst.
>> +  return Offset;
>> +}
>> +
>> +static llvm::Constant *getBadTypeidFn(CodeGenFunction &CGF) {
>> +  // void __cxa_bad_typeid();
>> +  llvm::FunctionType *FTy = llvm::FunctionType::get(CGF.VoidTy, false);
>> +
>> +  return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_bad_typeid");
>> +}
>> +
>> +bool ItaniumCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
>> +                                              QualType SrcRecordTy) {
>> +  return IsDeref;
>> +}
>> +
>> +void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
>> +  llvm::Value *Fn = getBadTypeidFn(CGF);
>> +  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
>> +  CGF.Builder.CreateUnreachable();
>> +}
>> +
>> +llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
>> +                                       QualType SrcRecordTy,
>> +                                       llvm::Value *ThisPtr,
>> +                                       llvm::Type *StdTypeInfoPtrTy) {
>> +  llvm::Value *Value =
>> +      CGF.GetVTablePtr(ThisPtr, StdTypeInfoPtrTy->getPointerTo());
>> +
>> +  // Load the type info.
>> +  Value = CGF.Builder.CreateConstInBoundsGEP1_64(Value, -1ULL);
>> +  return CGF.Builder.CreateLoad(Value);
>> +}
>> +
>> +bool ItaniumCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
>> +                                                       QualType
>> SrcRecordTy) {
>> +  return SrcIsPtr;
>> +}
>> +
>> +llvm::Value *ItaniumCXXABI::EmitDynamicCastCall(
>> +    CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
>> +    QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
>> +  llvm::Type *PtrDiffLTy =
>> +      CGF.ConvertType(CGF.getContext().getPointerDiffType());
>> +  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
>> +
>> +  llvm::Value *SrcRTTI =
>> +      CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
>> +  llvm::Value *DestRTTI =
>> +      CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
>> +
>> +  // Compute the offset hint.
>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
>> +  const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
>> +  llvm::Value *OffsetHint = llvm::ConstantInt::get(
>> +      PtrDiffLTy,
>> +      computeOffsetHint(CGF.getContext(), SrcDecl,
>> DestDecl).getQuantity());
>> +
>> +  // Emit the call to __dynamic_cast.
>> +  Value = CGF.EmitCastToVoidPtr(Value);
>> +
>> +  llvm::Value *args[] = {Value, SrcRTTI, DestRTTI, OffsetHint};
>> +  Value = CGF.EmitNounwindRuntimeCall(getItaniumDynamicCastFn(CGF),
>> args);
>> +  Value = CGF.Builder.CreateBitCast(Value, DestLTy);
>> +
>> +  /// C++ [expr.dynamic.cast]p9:
>> +  ///   A failed cast to reference type throws std::bad_cast
>> +  if (DestTy->isReferenceType()) {
>> +    llvm::BasicBlock *BadCastBlock =
>> +        CGF.createBasicBlock("dynamic_cast.bad_cast");
>> +
>> +    llvm::Value *IsNull = CGF.Builder.CreateIsNull(Value);
>> +    CGF.Builder.CreateCondBr(IsNull, BadCastBlock, CastEnd);
>> +
>> +    CGF.EmitBlock(BadCastBlock);
>> +    EmitBadCastCall(CGF);
>> +  }
>> +
>> +  return Value;
>> +}
>> +
>> +llvm::Value *ItaniumCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF,
>> +                                                  llvm::Value *Value,
>> +                                                  QualType SrcRecordTy,
>> +                                                  QualType DestTy) {
>> +  llvm::Type *PtrDiffLTy =
>> +      CGF.ConvertType(CGF.getContext().getPointerDiffType());
>> +  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
>> +
>> +  // Get the vtable pointer.
>> +  llvm::Value *VTable = CGF.GetVTablePtr(Value,
>> PtrDiffLTy->getPointerTo());
>> +
>> +  // Get the offset-to-top from the vtable.
>> +  llvm::Value *OffsetToTop =
>> +      CGF.Builder.CreateConstInBoundsGEP1_64(VTable, -2ULL);
>> +  OffsetToTop = CGF.Builder.CreateLoad(OffsetToTop, "offset.to.top");
>> +
>> +  // Finally, add the offset to the pointer.
>> +  Value = CGF.EmitCastToVoidPtr(Value);
>> +  Value = CGF.Builder.CreateInBoundsGEP(Value, OffsetToTop);
>> +
>> +  return CGF.Builder.CreateBitCast(Value, DestLTy);
>> +}
>> +
>> +bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
>> +  llvm::Value *Fn = getBadCastFn(CGF);
>> +  CGF.EmitRuntimeCallOrInvoke(Fn).setDoesNotReturn();
>> +  CGF.Builder.CreateUnreachable();
>> +  return true;
>> +}
>> +
>>  llvm::Value *
>>  ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
>>                                           llvm::Value *This,
>>
>> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=211473&r1=211472&r2=211473&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Sun Jun 22 14:05:33 2014
>> @@ -21,6 +21,7 @@
>>  #include "clang/AST/DeclCXX.h"
>>  #include "clang/AST/VTableBuilder.h"
>>  #include "llvm/ADT/StringSet.h"
>> +#include "llvm/IR/CallSite.h"
>>
>>  using namespace clang;
>>  using namespace CodeGen;
>> @@ -56,6 +57,26 @@ public:
>>                                        llvm::Value *ptr,
>>                                        QualType type) override;
>>
>> +  bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy)
>> override;
>> +  void EmitBadTypeidCall(CodeGenFunction &CGF) override;
>> +  llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
>> +                          llvm::Value *ThisPtr,
>> +                          llvm::Type *StdTypeInfoPtrTy) override;
>> +
>> +  bool shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
>> +                                          QualType SrcRecordTy) override;
>> +
>> +  llvm::Value *EmitDynamicCastCall(CodeGenFunction &CGF, llvm::Value
>> *Value,
>> +                                   QualType SrcRecordTy, QualType DestTy,
>> +                                   QualType DestRecordTy,
>> +                                   llvm::BasicBlock *CastEnd) override;
>> +
>> +  llvm::Value *EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value
>> *Value,
>> +                                     QualType SrcRecordTy,
>> +                                     QualType DestTy) override;
>> +
>> +  bool EmitBadCastCall(CodeGenFunction &CGF) override;
>> +
>>    llvm::Value *
>>    GetVirtualBaseClassOffset(CodeGenFunction &CGF, llvm::Value *This,
>>                              const CXXRecordDecl *ClassDecl,
>> @@ -469,6 +490,129 @@ llvm::Value *MicrosoftCXXABI::adjustToCo
>>    return ptr;
>>  }
>>
>> +/// \brief Gets the offset to the virtual base that contains the vfptr
>> for
>> +/// MS-ABI polymorphic types.
>> +static llvm::Value *getPolymorphicOffset(CodeGenFunction &CGF,
>> +                                         const CXXRecordDecl *RD,
>> +                                         llvm::Value *Value) {
>> +  const ASTContext &Context = RD->getASTContext();
>> +  for (const CXXBaseSpecifier &Base : RD->vbases())
>> +    if (Context.getASTRecordLayout(Base.getType()->getAsCXXRecordDecl())
>> +            .hasExtendableVFPtr())
>> +      return CGF.CGM.getCXXABI().GetVirtualBaseClassOffset(
>> +          CGF, Value, RD, Base.getType()->getAsCXXRecordDecl());
>> +  llvm_unreachable("One of our vbases should be polymorphic.");
>> +}
>> +
>> +static std::pair<llvm::Value *, llvm::Value *>
>> +performBaseAdjustment(CodeGenFunction &CGF, llvm::Value *Value,
>> +                      QualType SrcRecordTy) {
>> +  Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy);
>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
>> +
>> +  if (CGF.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr())
>> +    return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0));
>> +
>> +  // Perform a base adjustment.
>> +  llvm::Value *Offset = getPolymorphicOffset(CGF, SrcDecl, Value);
>> +  Value = CGF.Builder.CreateInBoundsGEP(Value, Offset);
>> +  Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty);
>> +  return std::make_pair(Value, Offset);
>> +}
>> +
>> +bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref,
>> +                                                QualType SrcRecordTy) {
>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
>> +  return IsDeref &&
>> +
>> !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
>> +}
>> +
>> +static llvm::CallSite emitRTtypeidCall(CodeGenFunction &CGF,
>> +                                       llvm::Value *Argument) {
>> +  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
>> +  llvm::FunctionType *FTy =
>> +      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false);
>> +  llvm::Value *Args[] = {Argument};
>> +  llvm::Constant *Fn = CGF.CGM.CreateRuntimeFunction(FTy, "__RTtypeid");
>> +  return CGF.EmitRuntimeCallOrInvoke(Fn, Args);
>> +}
>> +
>> +void MicrosoftCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
>> +  llvm::CallSite Call =
>> +      emitRTtypeidCall(CGF, llvm::Constant::getNullValue(CGM.VoidPtrTy));
>> +  Call.setDoesNotReturn();
>> +  CGF.Builder.CreateUnreachable();
>> +}
>> +
>> +llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF,
>> +                                         QualType SrcRecordTy,
>> +                                         llvm::Value *ThisPtr,
>> +                                         llvm::Type *StdTypeInfoPtrTy) {
>> +  llvm::Value *Offset;
>> +  std::tie(ThisPtr, Offset) = performBaseAdjustment(CGF, ThisPtr,
>> SrcRecordTy);
>> +  return CGF.Builder.CreateBitCast(
>> +      emitRTtypeidCall(CGF, ThisPtr).getInstruction(), StdTypeInfoPtrTy);
>> +}
>> +
>> +bool MicrosoftCXXABI::shouldDynamicCastCallBeNullChecked(bool SrcIsPtr,
>> +                                                         QualType
>> SrcRecordTy) {
>> +  const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
>> +  return SrcIsPtr &&
>> +
>> !CGM.getContext().getASTRecordLayout(SrcDecl).hasExtendableVFPtr();
>> +}
>> +
>> +llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall(
>> +    CodeGenFunction &CGF, llvm::Value *Value, QualType SrcRecordTy,
>> +    QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastEnd) {
>> +  llvm::Type *DestLTy = CGF.ConvertType(DestTy);
>> +
>> +  llvm::Value *SrcRTTI =
>> +      CGF.CGM.GetAddrOfRTTIDescriptor(SrcRecordTy.getUnqualifiedType());
>> +  llvm::Value *DestRTTI =
>> +      CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());
>> +
>> +  llvm::Value *Offset;
>> +  std::tie(Value, Offset) = performBaseAdjustment(CGF, Value,
>> SrcRecordTy);
>> +
>> +  // PVOID __RTDynamicCast(
>> +  //   PVOID inptr,
>> +  //   LONG VfDelta,
>> +  //   PVOID SrcType,
>> +  //   PVOID TargetType,
>> +  //   BOOL isReference)
>> +  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy, CGF.Int32Ty, CGF.Int8PtrTy,
>> +                            CGF.Int8PtrTy, CGF.Int32Ty};
>> +  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
>> +      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
>> +      "__RTDynamicCast");
>> +  llvm::Value *Args[] = {
>> +      Value, Offset, SrcRTTI, DestRTTI,
>> +      llvm::ConstantInt::get(CGF.Int32Ty, DestTy->isReferenceType())};
>> +  Value = CGF.EmitRuntimeCallOrInvoke(Function, Args).getInstruction();
>> +  return CGF.Builder.CreateBitCast(Value, DestLTy);
>> +}
>> +
>> +llvm::Value *
>> +MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, llvm::Value
>> *Value,
>> +                                       QualType SrcRecordTy,
>> +                                       QualType DestTy) {
>> +  llvm::Value *Offset;
>> +  std::tie(Value, Offset) = performBaseAdjustment(CGF, Value,
>> SrcRecordTy);
>> +
>> +  // PVOID __RTCastToVoid(
>> +  //   PVOID inptr)
>> +  llvm::Type *ArgTypes[] = {CGF.Int8PtrTy};
>> +  llvm::Constant *Function = CGF.CGM.CreateRuntimeFunction(
>> +      llvm::FunctionType::get(CGF.Int8PtrTy, ArgTypes, false),
>> +      "__RTCastToVoid");
>> +  llvm::Value *Args[] = {Value};
>> +  return CGF.EmitRuntimeCall(Function, Args);
>> +}
>> +
>> +bool MicrosoftCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
>> +  return false;
>> +}
>> +
>>  llvm::Value *
>>  MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
>>                                             llvm::Value *This,
>>
>> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp?rev=211473&r1=211472&r2=211473&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp Sun Jun 22
>> 14:05:33 2014
>> @@ -1,158 +1,130 @@
>> -// RUN: %clang_cc1 -emit-llvm -O2 -optzns -o - -triple=i386-pc-win32
>> 2>/dev/null %s | FileCheck %s
>> -// REQUIRES: asserts
>> +// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s |
>> FileCheck %s
>>
>>  struct S { char a; };
>> -struct V { virtual void f(){} };
>> +struct V { virtual void f(); };
>>  struct A : virtual V {};
>>  struct B : S, virtual V {};
>>  struct T {};
>>
>>  T* test0() { return dynamic_cast<T*>((B*)0); }
>> -// CHECK: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"() #0 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   ret %struct.T* null
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define noalias %struct.T* @"\01?test0@@YAPAUT@@XZ"()
>> +// CHECK:   ret %struct.T* null
>>
>>  T* test1(V* x) { return &dynamic_cast<T&>(*x); }
>> -// CHECK: define %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V*
>> %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = bitcast %struct.V* %x to i8*
>> -// CHECK-NEXT:   %1 = tail call i8* @__RTDynamicCast(i8* %0, i32 0, i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8" to i8*), i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 1)
>> #2
>> -// CHECK-NEXT:   %2 = bitcast i8* %1 to %struct.T*
>> -// CHECK-NEXT:   ret %struct.T* %2
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.T* @"\01?test1@@YAPAUT@@PAUV@@@Z"(%struct.V*
>> %x)
>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.V* %x to i8*
>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
>> [[CAST]], i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8"
>> to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to
>> i8*), i32 1)
>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
>>
>>  T* test2(A* x) { return &dynamic_cast<T&>(*x); }
>> -// CHECK: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A*
>> %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = bitcast %struct.A* %x to i8*
>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %x to i8**
>> -// CHECK-NEXT:   %vbtable = load i8** %1, align 4
>> -// CHECK-NEXT:   %2 = getelementptr inbounds i8* %vbtable, i32 4
>> -// CHECK-NEXT:   %3 = bitcast i8* %2 to i32*
>> -// CHECK-NEXT:   %vbase_offs = load i32* %3, align 4
>> -// CHECK-NEXT:   %4 = getelementptr inbounds i8* %0, i32 %vbase_offs
>> -// CHECK-NEXT:   %5 = tail call i8* @__RTDynamicCast(i8* %4, i32
>> %vbase_offs, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8"
>> to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to
>> i8*), i32 1) #2
>> -// CHECK-NEXT:   %6 = bitcast i8* %5 to %struct.T*
>> -// CHECK-NEXT:   ret %struct.T* %6
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.T* @"\01?test2@@YAPAUT@@PAUA@@@Z"(%struct.A*
>> %x)
>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.A* %x to i8*
>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]],
>> i32 4
>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4
>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32
>> [[VBOFFS]]
>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
>> [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUT@@@8" to i8*), i32 1)
>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
>>
>>  T* test3(B* x) { return &dynamic_cast<T&>(*x); }
>> -// CHECK: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B*
>> %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = getelementptr inbounds %struct.B* %x, i32 0, i32
>> 0, i32 0
>> -// CHECK-NEXT:   %vbptr = getelementptr inbounds i8* %0, i32 4
>> -// CHECK-NEXT:   %1 = bitcast i8* %vbptr to i8**
>> -// CHECK-NEXT:   %vbtable = load i8** %1, align 4
>> -// CHECK-NEXT:   %2 = getelementptr inbounds i8* %vbtable, i32 4
>> -// CHECK-NEXT:   %3 = bitcast i8* %2 to i32*
>> -// CHECK-NEXT:   %vbase_offs = load i32* %3, align 4
>> -// CHECK-NEXT:   %4 = add nsw i32 %vbase_offs, 4
>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %0, i32 %4
>> -// CHECK-NEXT:   %6 = tail call i8* @__RTDynamicCast(i8* %5, i32 %4, i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 1)
>> #2
>> -// CHECK-NEXT:   %7 = bitcast i8* %6 to %struct.T*
>> -// CHECK-NEXT:   ret %struct.T* %7
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.T* @"\01?test3@@YAPAUT@@PAUB@@@Z"(%struct.B*
>> %x)
>> +// CHECK:        [[VOIDP:%.*]] = getelementptr inbounds %struct.B* %x,
>> i32 0, i32 0, i32 0
>> +// CHECK-NEXT:   [[VBPTR:%.*]] = getelementptr inbounds i8* [[VOIDP]],
>> i32 4
>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast i8* [[VBPTR:%.*]] to i8**
>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]],
>> i32 4
>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST]], align 4
>> +// CHECK-NEXT:   [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32
>> [[DELTA]]
>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
>> [[ADJ]], i32 [[DELTA]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUT@@@8" to i8*), i32 1)
>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
>>
>>  T* test4(V* x) { return dynamic_cast<T*>(x); }
>> -// CHECK: define %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V*
>> %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = bitcast %struct.V* %x to i8*
>> -// CHECK-NEXT:   %1 = tail call i8* @__RTDynamicCast(i8* %0, i32 0, i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8" to i8*), i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 0)
>> #2
>> -// CHECK-NEXT:   %2 = bitcast i8* %1 to %struct.T*
>> -// CHECK-NEXT:   ret %struct.T* %2
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.T* @"\01?test4@@YAPAUT@@PAUV@@@Z"(%struct.V*
>> %x)
>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.V* %x to i8*
>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
>> [[CAST]], i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUV@@@8"
>> to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to
>> i8*), i32 0)
>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[CALL]] to %struct.T*
>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
>>
>>  T* test5(A* x) { return dynamic_cast<T*>(x); }
>> -// CHECK: define %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A*
>> %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = icmp eq %struct.A* %x, null
>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
>> %dynamic_cast.valid
>> -// CHECK: dynamic_cast.valid:                               ; preds =
>> %entry
>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %x to i8*
>> -// CHECK-NEXT:   %2 = bitcast %struct.A* %x to i8**
>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %1, i32 %vbase_offs
>> -// CHECK-NEXT:   %6 = tail call i8* @__RTDynamicCast(i8* %5, i32
>> %vbase_offs, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8"
>> to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to
>> i8*), i32 0) #2
>> -// CHECK-NEXT:   %phitmp = bitcast i8* %6 to %struct.T*
>> -// CHECK-NEXT:   br label %dynamic_cast.call
>> -// CHECK: dynamic_cast.call:                                ; preds =
>> %dynamic_cast.valid, %entry
>> -// CHECK-NEXT:   %7 = phi %struct.T* [ %phitmp, %dynamic_cast.valid ], [
>> null, %entry ]
>> -// CHECK-NEXT:   ret %struct.T* %7
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.T* @"\01?test5@@YAPAUT@@PAUA@@@Z"(%struct.A*
>> %x)
>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.A* %x, null
>> +// CHECK-NEXT:   br i1 [[CHECK]]
>> +// CHECK:        [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]],
>> i32 4
>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32
>> [[VBOFFS]]
>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
>> [[ADJ]], i32 [[VBOFFS]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUA@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUT@@@8" to i8*), i32 0)
>> +// CHECK-NEXT:   [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
>> +// CHECK-NEXT:   br label
>> +// CHECK:        [[RET:%.*]] = phi %struct.T*
>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
>>
>>  T* test6(B* x) { return dynamic_cast<T*>(x); }
>> -// CHECK: define %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B*
>> %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = icmp eq %struct.B* %x, null
>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
>> %dynamic_cast.valid
>> -// CHECK: dynamic_cast.valid:                               ; preds =
>> %entry
>> -// CHECK-NEXT:   %1 = getelementptr inbounds %struct.B* %x, i32 0, i32
>> 0, i32 0
>> -// CHECK-NEXT:   %vbptr = getelementptr inbounds i8* %1, i32 4
>> -// CHECK-NEXT:   %2 = bitcast i8* %vbptr to i8**
>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
>> -// CHECK-NEXT:   %5 = add nsw i32 %vbase_offs, 4
>> -// CHECK-NEXT:   %6 = getelementptr inbounds i8* %1, i32 %5
>> -// CHECK-NEXT:   %7 = tail call i8* @__RTDynamicCast(i8* %6, i32 %5, i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i8*
>> bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUT@@@8" to i8*), i32 0)
>> #2
>> -// CHECK-NEXT:   %phitmp = bitcast i8* %7 to %struct.T*
>> -// CHECK-NEXT:   br label %dynamic_cast.call
>> -// CHECK: dynamic_cast.call:                                ; preds =
>> %dynamic_cast.valid, %entry
>> -// CHECK-NEXT:   %8 = phi %struct.T* [ %phitmp, %dynamic_cast.valid ], [
>> null, %entry ]
>> -// CHECK-NEXT:   ret %struct.T* %8
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.T* @"\01?test6@@YAPAUT@@PAUB@@@Z"(%struct.B*
>> %x)
>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.B* %x, null
>> +// CHECK-NEXT:   br i1 [[CHECK]]
>> +// CHECK:        [[CAST:%.*]] = getelementptr inbounds %struct.B* %x,
>> i32 0, i32 0, i32 0
>> +// CHECK-NEXT:   [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]],
>> i32 4
>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8**
>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]],
>> i32 4
>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
>> +// CHECK-NEXT:   [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32
>> [[DELTA]]
>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTDynamicCast(i8*
>> [[ADJ]], i32 [[DELTA]], i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUB@@@8" to i8*), i8* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUT@@@8" to i8*), i32 0)
>> +// CHECK-NEXT:   [[RES:%.*]] = bitcast i8* [[CALL]] to %struct.T*
>> +// CHECK-NEXT:   br label
>> +// CHECK:        [[RET:%.*]] = phi %struct.T*
>> +// CHECK-NEXT:   ret %struct.T* [[RET]]
>>
>>  void* test7(V* x) { return dynamic_cast<void*>(x); }
>> -// CHECK: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = bitcast %struct.V* %x to i8*
>> -// CHECK-NEXT:   %1 = tail call i8* @__RTCastToVoid(i8* %0) #2
>> -// CHECK-NEXT:   ret i8* %1
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define i8* @"\01?test7@@YAPAXPAUV@@@Z"(%struct.V* %x)
>> +// CHECK:        [[CAST:%.*]] = bitcast %struct.V* %x to i8*
>> +// CHECK-NEXT:   [[RET:%.*]] = tail call i8* @__RTCastToVoid(i8*
>> [[CAST]])
>> +// CHECK-NEXT:   ret i8* [[RET]]
>>
>>  void* test8(A* x) { return dynamic_cast<void*>(x); }
>> -// CHECK: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = icmp eq %struct.A* %x, null
>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
>> %dynamic_cast.valid
>> -// CHECK: dynamic_cast.valid:                               ; preds =
>> %entry
>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %x to i8*
>> -// CHECK-NEXT:   %2 = bitcast %struct.A* %x to i8**
>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %1, i32 %vbase_offs
>> -// CHECK-NEXT:   %6 = tail call i8* @__RTCastToVoid(i8* %5) #2
>> -// CHECK-NEXT:   br label %dynamic_cast.call
>> -// CHECK: dynamic_cast.call:                                ; preds =
>> %dynamic_cast.valid, %entry
>> -// CHECK-NEXT:   %7 = phi i8* [ %6, %dynamic_cast.valid ], [ null,
>> %entry ]
>> -// CHECK-NEXT:   ret i8* %7
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define i8* @"\01?test8@@YAPAXPAUA@@@Z"(%struct.A* %x)
>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.A* %x, null
>> +// CHECK-NEXT:   br i1 [[CHECK]]
>> +// CHECK:        [[VOIDP:%.*]] = bitcast %struct.A* %x to i8*
>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast %struct.A* %x to i8**
>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]],
>> i32 4
>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[VOIDP]], i32
>> [[VBOFFS]]
>> +// CHECK-NEXT:   [[RES:%.*]] = tail call i8* @__RTCastToVoid(i8* [[ADJ]])
>> +// CHECK-NEXT:   br label
>> +// CHECK:        [[RET:%.*]] = phi i8*
>> +// CHECK-NEXT:   ret i8* [[RET]]
>>
>>  void* test9(B* x) { return dynamic_cast<void*>(x); }
>> -// CHECK: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x) #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %0 = icmp eq %struct.B* %x, null
>> -// CHECK-NEXT:   br i1 %0, label %dynamic_cast.call, label
>> %dynamic_cast.valid
>> -// CHECK: dynamic_cast.valid:                               ; preds =
>> %entry
>> -// CHECK-NEXT:   %1 = getelementptr inbounds %struct.B* %x, i32 0, i32
>> 0, i32 0
>> -// CHECK-NEXT:   %vbptr = getelementptr inbounds i8* %1, i32 4
>> -// CHECK-NEXT:   %2 = bitcast i8* %vbptr to i8**
>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
>> -// CHECK-NEXT:   %5 = add nsw i32 %vbase_offs, 4
>> -// CHECK-NEXT:   %6 = getelementptr inbounds i8* %1, i32 %5
>> -// CHECK-NEXT:   %7 = tail call i8* @__RTCastToVoid(i8* %6) #2
>> -// CHECK-NEXT:   br label %dynamic_cast.call
>> -// CHECK: dynamic_cast.call:                                ; preds =
>> %dynamic_cast.valid, %entry
>> -// CHECK-NEXT:   %8 = phi i8* [ %7, %dynamic_cast.valid ], [ null,
>> %entry ]
>> -// CHECK-NEXT:   ret i8* %8
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define i8* @"\01?test9@@YAPAXPAUB@@@Z"(%struct.B* %x)
>> +// CHECK:        [[CHECK:%.*]] = icmp eq %struct.B* %x, null
>> +// CHECK-NEXT:   br i1 [[CHECK]]
>> +// CHECK:        [[CAST:%.*]] = getelementptr inbounds %struct.B* %x,
>> i32 0, i32 0, i32 0
>> +// CHECK-NEXT:   [[VBPTR:%.*]] = getelementptr inbounds i8* [[CAST]],
>> i32 4
>> +// CHECK-NEXT:   [[BITCAST:%.*]] = bitcast i8* [[VBPTR]] to i8**
>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[BITCAST]], align 4
>> +// CHECK-NEXT:   [[VBOFFP:%.*]] = getelementptr inbounds i8* [[VBTBL]],
>> i32 4
>> +// CHECK-NEXT:   [[VBOFFPCAST:%.*]] = bitcast i8* [[VBOFFP]] to i32*
>> +// CHECK-NEXT:   [[VBOFFS:%.*]] = load i32* [[VBOFFPCAST:%.*]], align 4
>> +// CHECK-NEXT:   [[DELTA:%.*]] = add nsw i32 [[VBOFFS]], 4
>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[CAST]], i32
>> [[DELTA]]
>> +// CHECK-NEXT:   [[CALL:%.*]] = tail call i8* @__RTCastToVoid(i8*
>> [[ADJ]])
>> +// CHECK-NEXT:   br label
>> +// CHECK:        [[RET:%.*]] = phi i8*
>> +// CHECK-NEXT:   ret i8* [[RET]]
>> +
>>
>> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp?rev=211473&r1=211472&r2=211473&view=diff
>>
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-typeid.cpp Sun Jun 22
>> 14:05:33 2014
>> @@ -1,58 +1,45 @@
>> -// RUN: %clang_cc1 -emit-llvm -O2 -optzns -o - -triple=i386-pc-win32
>> 2>/dev/null %s | FileCheck %s
>> -// REQUIRES: asserts
>> +// RUN: %clang_cc1 -emit-llvm -O1 -o - -triple=i386-pc-win32 %s |
>> FileCheck %s
>>
>> -struct type_info { const char* raw_name() const; };
>> +struct type_info;
>>  namespace std { using ::type_info; }
>>
>> -struct V { virtual void f() {}; };
>> -struct A : virtual V {};
>> +struct V { virtual void f(); };
>> +struct A : virtual V { A(); };
>>
>> -A a;
>> -int b;
>> +extern A a;
>> +extern int b;
>>  A* fn();
>>
>>  const std::type_info* test0_typeid() { return &typeid(int); }
>> -// CHECK: define %struct.type_info* @"\01?test0_typeid@@YAPBUtype_info@@XZ"()
>> #0 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
>> (%"MSRTTITypeDescriptor\02"* @"\01??_R0H at 8" to %struct.type_info*)
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.type_info* @"\01?test0_typeid@
>> @YAPBUtype_info@@XZ"()
>> +// CHECK:   ret %struct.type_info* bitcast (%"MSRTTITypeDescriptor\02"*
>> @"\01??_R0H at 8" to %struct.type_info*)
>>
>>  const std::type_info* test1_typeid() { return &typeid(A); }
>> -// CHECK: define %struct.type_info* @"\01?test1_typeid@@YAPBUtype_info@@XZ"()
>> #0 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
>> (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8" to %struct.type_info*)
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.type_info* @"\01?test1_typeid@
>> @YAPBUtype_info@@XZ"()
>> +// CHECK:   ret %struct.type_info* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0?AUA@@@8" to %struct.type_info*)
>>
>>  const std::type_info* test2_typeid() { return &typeid(&a); }
>> -// CHECK: define %struct.type_info* @"\01?test2_typeid@@YAPBUtype_info@@XZ"()
>> #0 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
>> (%"MSRTTITypeDescriptor\07"* @"\01??_R0PAUA@@@8" to %struct.type_info*)
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.type_info* @"\01?test2_typeid@
>> @YAPBUtype_info@@XZ"()
>> +// CHECK:   ret %struct.type_info* bitcast (%"MSRTTITypeDescriptor\07"*
>> @"\01??_R0PAUA@@@8" to %struct.type_info*)
>>
>>  const std::type_info* test3_typeid() { return &typeid(*fn()); }
>> -// CHECK: define %struct.type_info* @"\01?test3_typeid@@YAPBUtype_info@@XZ"()
>> #1 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   %call = tail call %struct.A* @"\01?fn@@YAPAUA@@XZ"() #3
>> -// CHECK-NEXT:   %0 = icmp eq %struct.A* %call, null
>> -// CHECK-NEXT:   br i1 %0, label %type_id.call, label %type_id.valid
>> -// CHECK: type_id.valid:                                    ; preds =
>> %entry
>> -// CHECK-NEXT:   %1 = bitcast %struct.A* %call to i8*
>> -// CHECK-NEXT:   %2 = bitcast %struct.A* %call to i8**
>> -// CHECK-NEXT:   %vbtable = load i8** %2, align 4
>> -// CHECK-NEXT:   %3 = getelementptr inbounds i8* %vbtable, i32 4
>> -// CHECK-NEXT:   %4 = bitcast i8* %3 to i32*
>> -// CHECK-NEXT:   %vbase_offs = load i32* %4, align 4
>> -// CHECK-NEXT:   %5 = getelementptr inbounds i8* %1, i32 %vbase_offs
>> -// CHECK-NEXT:   br label %type_id.call
>> -// CHECK: type_id.call:                                     ; preds =
>> %type_id.valid, %entry
>> -// CHECK-NEXT:   %6 = phi i8* [ %5, %type_id.valid ], [ null, %entry ]
>> -// CHECK-NEXT:   %7 = tail call i8* @__RTtypeid(i8* %6) #3
>> -// CHECK-NEXT:   %8 = bitcast i8* %7 to %struct.type_info*
>> -// CHECK-NEXT:   ret %struct.type_info* %8
>> -// CHECK-NEXT: }
>> +// CHECK-LABEL: define %struct.type_info* @"\01?test3_typeid@
>> @YAPBUtype_info@@XZ"()
>> +// CHECK:        [[CALL:%.*]] = tail call %struct.A* @"\01?fn@@YAPAUA@
>> @XZ"()
>> +// CHECK-NEXT:   [[CMP:%.*]] = icmp eq %struct.A* [[CALL]], null
>> +// CHECK-NEXT:   br i1 [[CMP]]
>> +// CHECK:        tail call i8* @__RTtypeid(i8* null)
>> +// CHECK-NEXT:   unreachable
>> +// CHECK:        [[THIS:%.*]] = bitcast %struct.A* [[CALL]] to i8*
>> +// CHECK-NEXT:   [[VBTBLP:%.*]] = bitcast %struct.A* [[CALL]] to i8**
>> +// CHECK-NEXT:   [[VBTBL:%.*]] = load i8** [[VBTBLP]], align 4
>> +// CHECK-NEXT:   [[VBSLOT:%.*]] = getelementptr inbounds i8* [[VBTBL]],
>> i32 4
>> +// CHECK-NEXT:   [[VBITCST:%.*]] = bitcast i8* [[VBSLOT]] to i32*
>> +// CHECK-NEXT:   [[VBASE_OFFS:%.*]] = load i32* [[VBITCST]], align 4
>> +// CHECK-NEXT:   [[ADJ:%.*]] = getelementptr inbounds i8* [[THIS]], i32
>> [[VBASE_OFFS]]
>> +// CHECK-NEXT:   [[RT:%.*]] = tail call i8* @__RTtypeid(i8* [[ADJ]])
>> +// CHECK-NEXT:   [[RET:%.*]] = bitcast i8* [[RT]] to %struct.type_info*
>> +// CHECK-NEXT:   ret %struct.type_info* [[RET]]
>>
>>  const std::type_info* test4_typeid() { return &typeid(b); }
>> -// CHECK: define %struct.type_info* @"\01?test4_typeid@@YAPBUtype_info@@XZ"()
>> #0 {
>> -// CHECK-NEXT: entry:
>> -// CHECK-NEXT:   ret %struct.type_info* bitcast
>> (%"MSRTTITypeDescriptor\02"* @"\01??_R0H at 8" to %struct.type_info*)
>> -// CHECK-NEXT: }
>> +// CHECK: define %struct.type_info* @"\01?test4_typeid@@YAPBUtype_info@
>> @XZ"()
>> +// CHECK:   ret %struct.type_info* bitcast (%"MSRTTITypeDescriptor\02"*
>> @"\01??_R0H at 8" to %struct.type_info*)
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140622/25af2a8b/attachment.html>


More information about the cfe-commits mailing list