r209523 - [MS-ABI] Implements MS-compatible RTTI

Warren Hunt whunt at google.com
Fri May 23 09:07:43 PDT 2014


Author: whunt
Date: Fri May 23 11:07:43 2014
New Revision: 209523

URL: http://llvm.org/viewvc/llvm-project?rev=209523&view=rev
Log:
[MS-ABI] Implements MS-compatible RTTI
Enables the emission of MS-compatible RTTI data structures for use with 
typeid, dynamic_cast and exceptions.  Does not implement dynamic_cast 
or exceptions.  As an artiface, typeid works in some cases but proper 
support an testing will coming in a subsequent patch.

majnemer has fuzzed the results.  Test cases included.

Differential Revision: http://reviews.llvm.org/D3833



Added:
    cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp
    cfe/trunk/test/CodeGenCXX/microsoft-abi-rtti.cpp
Modified:
    cfe/trunk/include/clang/AST/Mangle.h
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGRTTI.cpp
    cfe/trunk/lib/CodeGen/CMakeLists.txt
    cfe/trunk/lib/CodeGen/CodeGenModule.h
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp

Modified: cfe/trunk/include/clang/AST/Mangle.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=209523&r1=209522&r2=209523&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Mangle.h (original)
+++ cfe/trunk/include/clang/AST/Mangle.h Fri May 23 11:07:43 2014
@@ -214,7 +214,7 @@ public:
                                         raw_ostream &) = 0;
 
   virtual void mangleCXXRTTIBaseClassDescriptor(
-      const CXXRecordDecl *Derived, uint32_t NVOffset, uint32_t VBPtrOffset,
+      const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
       uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) = 0;
 
   virtual void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=209523&r1=209522&r2=209523&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Fri May 23 11:07:43 2014
@@ -113,7 +113,7 @@ public:
   void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
   void mangleCXXRTTIName(QualType T, raw_ostream &Out) override;
   void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived,
-                                        uint32_t NVOffset, uint32_t VBPtrOffset,
+                                        uint32_t NVOffset, int32_t VBPtrOffset,
                                         uint32_t VBTableOffset, uint32_t Flags,
                                         raw_ostream &Out) override;
   void mangleCXXRTTIBaseClassArray(const CXXRecordDecl *Derived,
@@ -2258,7 +2258,7 @@ void MicrosoftMangleContextImpl::mangleC
 }
 
 void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassDescriptor(
-    const CXXRecordDecl *Derived, uint32_t NVOffset, uint32_t VBPtrOffset,
+    const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
     uint32_t VBTableOffset, uint32_t Flags, raw_ostream &Out) {
   MicrosoftCXXNameMangler Mangler(*this, Out);
   Mangler.getStream() << "\01??_R1";
@@ -2267,7 +2267,7 @@ void MicrosoftMangleContextImpl::mangleC
   Mangler.mangleNumber(VBTableOffset);
   Mangler.mangleNumber(Flags);
   Mangler.mangleName(Derived);
-  Mangler.getStream() << "@8";
+  Mangler.getStream() << "8";
 }
 
 void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray(
@@ -2275,7 +2275,7 @@ void MicrosoftMangleContextImpl::mangleC
   MicrosoftCXXNameMangler Mangler(*this, Out);
   Mangler.getStream() << "\01??_R2";
   Mangler.mangleName(Derived);
-  Mangler.getStream() << "@8";
+  Mangler.getStream() << "8";
 }
 
 void MicrosoftMangleContextImpl::mangleCXXRTTIClassHierarchyDescriptor(
@@ -2283,7 +2283,7 @@ void MicrosoftMangleContextImpl::mangleC
   MicrosoftCXXNameMangler Mangler(*this, Out);
   Mangler.getStream() << "\01??_R3";
   Mangler.mangleName(Derived);
-  Mangler.getStream() << "@8";
+  Mangler.getStream() << "8";
 }
 
 void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=209523&r1=209522&r2=209523&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri May 23 11:07:43 2014
@@ -2086,7 +2086,7 @@ LValue CodeGenFunction::EmitPredefinedLV
 /// integer, 1 for a floating point value, and -1 for anything else.
 llvm::Constant *CodeGenFunction::EmitCheckTypeDescriptor(QualType T) {
   // Only emit each type's descriptor once.
-  if (llvm::Constant *C = CGM.getTypeDescriptor(T))
+  if (llvm::Constant *C = CGM.getTypeDescriptorFromMap(T))
     return C;
 
   uint16_t TypeKind = -1;
@@ -2121,7 +2121,7 @@ llvm::Constant *CodeGenFunction::EmitChe
   GV->setUnnamedAddr(true);
 
   // Remember the descriptor for this type.
-  CGM.setTypeDescriptor(T, GV);
+  CGM.setTypeDescriptorInMap(T, GV);
 
   return GV;
 }

Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=209523&r1=209522&r2=209523&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Fri May 23 11:07:43 2014
@@ -22,7 +22,7 @@ using namespace clang;
 using namespace CodeGen;
 
 namespace {
-class RTTIBuilder {
+class ItaniumRTTIBuilder {
   CodeGenModule &CGM;  // Per-module state.
   llvm::LLVMContext &VMContext;
   
@@ -62,7 +62,7 @@ class RTTIBuilder {
   void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty);
   
 public:
-  RTTIBuilder(CodeGenModule &CGM) : CGM(CGM), 
+  ItaniumRTTIBuilder(CodeGenModule &CGM) : CGM(CGM), 
     VMContext(CGM.getModule().getContext()) { }
 
   // Pointer type info flags.
@@ -110,7 +110,7 @@ public:
 }
 
 llvm::GlobalVariable *
-RTTIBuilder::GetAddrOfTypeName(QualType Ty, 
+ItaniumRTTIBuilder::GetAddrOfTypeName(QualType Ty,
                                llvm::GlobalVariable::LinkageTypes Linkage) {
   SmallString<256> OutName;
   llvm::raw_svector_ostream Out(OutName);
@@ -132,7 +132,8 @@ RTTIBuilder::GetAddrOfTypeName(QualType
   return GV;
 }
 
-llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
+llvm::Constant *
+ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) {
   // Mangle the RTTI name.
   SmallString<256> OutName;
   llvm::raw_svector_ostream Out(OutName);
@@ -317,8 +318,8 @@ static bool ContainsIncompleteClassType(
 
 /// getTypeInfoLinkage - Return the linkage that the type info and type info
 /// name constants should have for the given type.
-static llvm::GlobalVariable::LinkageTypes 
-getTypeInfoLinkage(CodeGenModule &CGM, QualType Ty) {
+llvm::GlobalVariable::LinkageTypes 
+CodeGenModule::getTypeInfoLinkage(QualType Ty) {
   // Itanium C++ ABI 2.9.5p7:
   //   In addition, it and all of the intermediate abi::__pointer_type_info 
   //   structs in the chain down to the abi::__class_type_info for the
@@ -339,7 +340,7 @@ getTypeInfoLinkage(CodeGenModule &CGM, Q
 
   case VisibleNoLinkage:
   case ExternalLinkage:
-    if (!CGM.getLangOpts().RTTI) {
+    if (!getLangOpts().RTTI) {
       // RTTI is not enabled, which means that this type info struct is going
       // to be used for exception handling. Give it linkonce_odr linkage.
       return llvm::GlobalValue::LinkOnceODRLinkage;
@@ -350,7 +351,7 @@ getTypeInfoLinkage(CodeGenModule &CGM, Q
       if (RD->hasAttr<WeakAttr>())
         return llvm::GlobalValue::WeakODRLinkage;
       if (RD->isDynamicClass())
-        return CGM.getVTableLinkage(RD);
+        return getVTableLinkage(RD);
     }
 
     return llvm::GlobalValue::LinkOnceODRLinkage;
@@ -388,7 +389,7 @@ static bool CanUseSingleInheritance(cons
   return true;
 }
 
-void RTTIBuilder::BuildVTablePointer(const Type *Ty) {
+void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
   // abi::__class_type_info.
   static const char * const ClassTypeInfo =
     "_ZTVN10__cxxabiv117__class_type_infoE";
@@ -509,7 +510,7 @@ void RTTIBuilder::BuildVTablePointer(con
   Fields.push_back(VTable);
 }
 
-llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
+llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
   // We want to operate on the canonical type.
   Ty = CGM.getContext().getCanonicalType(Ty);
 
@@ -538,7 +539,7 @@ llvm::Constant *RTTIBuilder::BuildTypeIn
   if (IsStdLib)
     Linkage = llvm::GlobalValue::ExternalLinkage;
   else
-    Linkage = getTypeInfoLinkage(CGM, Ty);
+    Linkage = CGM.getTypeInfoLinkage(Ty);
 
   // Add the vtable pointer.
   BuildVTablePointer(cast<Type>(Ty));
@@ -699,18 +700,18 @@ static unsigned ComputeQualifierFlags(Qu
   unsigned Flags = 0;
 
   if (Quals.hasConst())
-    Flags |= RTTIBuilder::PTI_Const;
+    Flags |= ItaniumRTTIBuilder::PTI_Const;
   if (Quals.hasVolatile())
-    Flags |= RTTIBuilder::PTI_Volatile;
+    Flags |= ItaniumRTTIBuilder::PTI_Volatile;
   if (Quals.hasRestrict())
-    Flags |= RTTIBuilder::PTI_Restrict;
+    Flags |= ItaniumRTTIBuilder::PTI_Restrict;
 
   return Flags;
 }
 
 /// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
 /// for the given Objective-C object type.
-void RTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
+void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
   // Drop qualifiers.
   const Type *T = OT->getBaseType().getTypePtr();
   assert(isa<BuiltinType>(T) || isa<ObjCInterfaceType>(T));
@@ -728,18 +729,18 @@ void RTTIBuilder::BuildObjCObjectTypeInf
   QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
 
   // Everything else is single inheritance.
-  llvm::Constant *BaseTypeInfo = RTTIBuilder(CGM).BuildTypeInfo(SuperTy);
+  llvm::Constant *BaseTypeInfo = ItaniumRTTIBuilder(CGM).BuildTypeInfo(SuperTy);
   Fields.push_back(BaseTypeInfo);
 }
 
 /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single
 /// inheritance, according to the Itanium C++ ABI, 2.95p6b.
-void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
+void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
   // Itanium C++ ABI 2.9.5p6b:
   // It adds to abi::__class_type_info a single member pointing to the 
   // type_info structure for the base type,
   llvm::Constant *BaseTypeInfo = 
-    RTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
+    ItaniumRTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType());
   Fields.push_back(BaseTypeInfo);
 }
 
@@ -768,20 +769,20 @@ static unsigned ComputeVMIClassTypeInfoF
     if (!Bases.VirtualBases.insert(BaseDecl)) {
       // If this virtual base has been seen before, then the class is diamond
       // shaped.
-      Flags |= RTTIBuilder::VMI_DiamondShaped;
+      Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped;
     } else {
       if (Bases.NonVirtualBases.count(BaseDecl))
-        Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+        Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
     }
   } else {
     // Mark the non-virtual base as seen.
     if (!Bases.NonVirtualBases.insert(BaseDecl)) {
       // If this non-virtual base has been seen before, then the class has non-
       // diamond shaped repeated inheritance.
-      Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+      Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
     } else {
       if (Bases.VirtualBases.count(BaseDecl))
-        Flags |= RTTIBuilder::VMI_NonDiamondRepeat;
+        Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat;
     }
   }
 
@@ -806,7 +807,7 @@ static unsigned ComputeVMIClassTypeInfoF
 /// BuildVMIClassTypeInfo - Build an abi::__vmi_class_type_info, used for
 /// classes with bases that do not satisfy the abi::__si_class_type_info 
 /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
-void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
+void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
   llvm::Type *UnsignedIntLTy = 
     CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
   
@@ -847,7 +848,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(
   //   };
   for (const auto &Base : RD->bases()) {
     // The __base_type member points to the RTTI for the base type.
-    Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(Base.getType()));
+    Fields.push_back(ItaniumRTTIBuilder(CGM).BuildTypeInfo(Base.getType()));
 
     const CXXRecordDecl *BaseDecl = 
       cast<CXXRecordDecl>(Base.getType()->getAs<RecordType>()->getDecl());
@@ -882,7 +883,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(
 
 /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
 /// used for pointer types.
-void RTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {  
+void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
   Qualifiers Quals;
   QualType UnqualifiedPointeeTy = 
     CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
@@ -906,13 +907,14 @@ void RTTIBuilder::BuildPointerTypeInfo(Q
   //  __pointee is a pointer to the std::type_info derivation for the 
   //  unqualified type being pointed to.
   llvm::Constant *PointeeTypeInfo = 
-    RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+    ItaniumRTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
   Fields.push_back(PointeeTypeInfo);
 }
 
 /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info 
 /// struct, used for member pointer types.
-void RTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+void
+ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
   QualType PointeeTy = Ty->getPointeeType();
   
   Qualifiers Quals;
@@ -943,14 +945,15 @@ void RTTIBuilder::BuildPointerToMemberTy
   //   __pointee is a pointer to the std::type_info derivation for the 
   //   unqualified type being pointed to.
   llvm::Constant *PointeeTypeInfo = 
-    RTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
+    ItaniumRTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy);
   Fields.push_back(PointeeTypeInfo);
 
   // Itanium C++ ABI 2.9.5p9:
   //   __context is a pointer to an abi::__class_type_info corresponding to the
   //   class type containing the member pointed to 
   //   (e.g., the "A" in "int A::*").
-  Fields.push_back(RTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
+  Fields.push_back(
+      ItaniumRTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0)));
 }
 
 llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty,
@@ -965,15 +968,17 @@ llvm::Constant *CodeGenModule::GetAddrOf
       LangOpts.ObjCRuntime.isGNUFamily())
     return ObjCRuntime->GetEHType(Ty);
 
-  return RTTIBuilder(*this).BuildTypeInfo(Ty);
+  if (getTarget().getCXXABI().isMicrosoft())
+    return getMSTypeDescriptor(Ty);
+  return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty);
 }
 
 void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) {
   QualType PointerType = Context.getPointerType(Type);
   QualType PointerTypeConst = Context.getPointerType(Type.withConst());
-  RTTIBuilder(*this).BuildTypeInfo(Type, true);
-  RTTIBuilder(*this).BuildTypeInfo(PointerType, true);
-  RTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
+  ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, true);
+  ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, true);
+  ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true);
 }
 
 void CodeGenModule::EmitFundamentalRTTIDescriptors() {

Modified: cfe/trunk/lib/CodeGen/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CMakeLists.txt?rev=209523&r1=209522&r2=209523&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CMakeLists.txt (original)
+++ cfe/trunk/lib/CodeGen/CMakeLists.txt Fri May 23 11:07:43 2014
@@ -60,6 +60,7 @@ add_clang_library(clangCodeGen
   CodeGenTypes.cpp
   ItaniumCXXABI.cpp
   MicrosoftCXXABI.cpp
+  MicrosoftRTTI.cpp
   ModuleBuilder.cpp
   TargetInfo.cpp
 

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=209523&r1=209522&r2=209523&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.h Fri May 23 11:07:43 2014
@@ -528,10 +528,10 @@ public:
     AtomicGetterHelperFnMap[Ty] = Fn;
   }
 
-  llvm::Constant *getTypeDescriptor(QualType Ty) {
+  llvm::Constant *getTypeDescriptorFromMap(QualType Ty) {
     return TypeDescriptorMap[Ty];
   }
-  void setTypeDescriptor(QualType Ty, llvm::Constant *C) {
+  void setTypeDescriptorInMap(QualType Ty, llvm::Constant *C) {
     TypeDescriptorMap[Ty] = C;
   }
 
@@ -710,6 +710,12 @@ public:
   /// The type of a generic block literal.
   llvm::Type *getGenericBlockLiteralType();
 
+  /// \brief Gets or a creats a Microsoft TypeDescriptor.
+  llvm::Constant *getMSTypeDescriptor(QualType Ty);
+  /// \brief Gets or a creats a Microsoft CompleteObjectLocator.
+  llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD,
+                                                   const VPtrInfo *Info);
+
   /// Gets the address of a block which requires no captures.
   llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *);
   
@@ -945,6 +951,9 @@ public:
     F->setLinkage(getFunctionLinkage(GD));
   }
 
+  /// \brief Returns the appropriate linkage for the TypeInfo struct for a type.
+  llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty);
+
   /// Return the appropriate linkage for the vtable, VTT, and type information
   /// of the given class.
   llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);

Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=209523&r1=209522&r2=209523&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri May 23 11:07:43 2014
@@ -897,14 +897,15 @@ void MicrosoftCXXABI::emitVTableDefiniti
   VPtrInfoVector VFPtrs = VFTContext.getVFPtrOffsets(RD);
   llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
 
-  for (VPtrInfoVector::iterator I = VFPtrs.begin(), E = VFPtrs.end(); I != E;
-       ++I) {
-    llvm::GlobalVariable *VTable = getAddrOfVTable(RD, (*I)->FullOffsetInMDC);
+  for (VPtrInfo *Info : VFPtrs) {
+    llvm::GlobalVariable *VTable = getAddrOfVTable(RD, Info->FullOffsetInMDC);
     if (VTable->hasInitializer())
       continue;
+    if (getContext().getLangOpts().RTTI)
+      CGM.getMSCompleteObjectLocator(RD, Info);
 
     const VTableLayout &VTLayout =
-        VFTContext.getVFTableLayout(RD, (*I)->FullOffsetInMDC);
+      VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC);
     llvm::Constant *Init = CGVT.CreateVTableInitializer(
         RD, VTLayout.vtable_component_begin(),
         VTLayout.getNumVTableComponents(), VTLayout.vtable_thunk_begin(),

Added: cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp?rev=209523&view=auto
==============================================================================
--- cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp (added)
+++ cfe/trunk/lib/CodeGen/MicrosoftRTTI.cpp Fri May 23 11:07:43 2014
@@ -0,0 +1,447 @@
+//===--- CGCXXRTTI.cpp - Emit LLVM Code for C++ RTTI descriptors ----------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with C++ code generation of RTTI descriptors.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenModule.h"
+#include "CGCXXABI.h"
+#include "CGObjCRuntime.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Type.h"
+#include "clang/Frontend/CodeGenOptions.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+// MS RTTI Overview:
+// The run time type information emitted by cl.exe contains 5 distinct types of
+// structures.  Many of them reference each other.
+//
+// TypeInfo:  Static classes that are returned by typeid.
+//
+// CompleteObjectLocator:  Referenced by vftables.  They contain information
+//   required for dynamic casting, including OffsetFromTop.  They also contain
+//   a reference to the TypeInfo for the type and a reference to the
+//   CompleteHierarchyDescriptor for the type.
+//
+// ClassHieararchyDescriptor: Contains information about a class hierarchy.
+//   Used during dynamic_cast to walk a class hierarchy.  References a base
+//   class array and the size of said array.
+//
+// BaseClassArray: Contains a list of classes in a hierarchy.  BaseClassArray is
+//   somewhat of a misnomer because the most derived class is also in the list
+//   as well as multiple copies of virtual bases (if they occur multiple times
+//   in the hiearchy.)  The BaseClassArray contains one BaseClassDescriptor for
+//   every path in the hierarchy, in pre-order depth first order.  Note, we do
+//   not declare a specific llvm type for BaseClassArray, it's merely an array
+//   of BaseClassDescriptor pointers.
+//
+// BaseClassDescriptor: Contains information about a class in a class hierarchy.
+//   BaseClassDescriptor is also somewhat of a misnomer for the same reason that
+//   BaseClassArray is.  It contains information about a class within a
+//   hierarchy such as: is this base is ambiguous and what is its offset in the
+//   vbtable.  The names of the BaseClassDescriptors have all of their fields
+//   mangled into them so they can be aggressively deduplicated by the linker.
+
+// 5 routines for constructing the llvm types for MS RTTI structs.
+llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM);
+
+static llvm::StructType *getTypeDescriptorType(CodeGenModule &CGM,
+                                               StringRef TypeInfoString) {
+  llvm::SmallString<32> TDTypeName("MSRTTITypeDescriptor");
+  TDTypeName += TypeInfoString.size();
+  if (auto Type = CGM.getModule().getTypeByName(TDTypeName))
+    return Type;
+  llvm::Type *FieldTypes[] = {
+      CGM.Int8PtrPtrTy,
+      CGM.Int8PtrTy,
+      llvm::ArrayType::get(CGM.Int8Ty, TypeInfoString.size() + 1)};
+  return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, TDTypeName);
+}
+
+static llvm::StructType *getBaseClassDescriptorType(CodeGenModule &CGM) {
+  static const char Name[] = "MSRTTIBaseClassDescriptor";
+  if (auto Type = CGM.getModule().getTypeByName(Name))
+    return Type;
+  llvm::Type *FieldTypes[] = {
+      CGM.Int8PtrTy,
+      CGM.IntTy,
+      CGM.IntTy,
+      CGM.IntTy,
+      CGM.IntTy,
+      CGM.IntTy,
+      getClassHierarchyDescriptorType(CGM)->getPointerTo()};
+  return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
+}
+
+static llvm::StructType *getClassHierarchyDescriptorType(CodeGenModule &CGM) {
+  static const char Name[] = "MSRTTIClassHierarchyDescriptor";
+  if (auto Type = CGM.getModule().getTypeByName(Name))
+    return Type;
+  // Forward declare RTTIClassHierarchyDescriptor to break a cycle.
+  llvm::StructType *Type = llvm::StructType::create(CGM.getLLVMContext(), Name);
+  llvm::Type *FieldTypes[] = {
+    CGM.IntTy,
+    CGM.IntTy,
+    CGM.IntTy,
+    getBaseClassDescriptorType(CGM)->getPointerTo()->getPointerTo()};
+  Type->setBody(FieldTypes);
+  return Type;
+}
+
+static llvm::StructType *getCompleteObjectLocatorType(CodeGenModule &CGM) {
+  static const char Name[] = "MSRTTICompleteObjectLocator";
+  if (auto Type = CGM.getModule().getTypeByName(Name))
+    return Type;
+  llvm::Type *FieldTypes[] = {
+    CGM.IntTy,
+    CGM.IntTy,
+    CGM.IntTy,
+    CGM.Int8PtrTy,
+    getClassHierarchyDescriptorType(CGM)->getPointerTo() };
+  return llvm::StructType::create(CGM.getLLVMContext(), FieldTypes, Name);
+}
+
+static llvm::GlobalVariable *getTypeInfoVTable(CodeGenModule &CGM) {
+  StringRef MangledName("\01??_7type_info@@6B@");
+  if (auto VTable = CGM.getModule().getNamedGlobal(MangledName))
+    return VTable;
+  return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy,
+                                  /*Constant=*/true,
+                                  llvm::GlobalVariable::ExternalLinkage,
+                                  /*Initializer=*/0, MangledName);
+}
+
+namespace {
+
+/// \brief A Helper struct that stores information about a class in a class
+/// hierarchy.  The information stored in these structs struct is used during
+/// the generation of ClassHierarchyDescriptors and BaseClassDescriptors.
+// During RTTI creation, MSRTTIClasses are stored in a contiguous array with
+// implicit depth first pre-order tree connectivity.  getFirstChild and
+// getNextSibling allow us to walk the tree efficiently.
+struct MSRTTIClass {
+  enum {
+    IsPrivateOnPath = 1 | 8,
+    IsAmbiguous = 2,
+    IsPrivate = 4,
+    IsVirtual = 16,
+    HasHierarchyDescriptor = 64
+  };
+  MSRTTIClass(const CXXRecordDecl *RD) : RD(RD) {}
+  uint32_t initialize(const MSRTTIClass *Parent,
+                      const CXXBaseSpecifier *Specifier);
+
+  MSRTTIClass *getFirstChild() { return this + 1; }
+  static MSRTTIClass *getNextChild(MSRTTIClass *Child) {
+    return Child + 1 + Child->NumBases;
+  }
+
+  const CXXRecordDecl *RD, *VirtualRoot;
+  uint32_t Flags, NumBases, OffsetInVBase;
+};
+
+/// \brief Recursively initialize the base class array.
+uint32_t MSRTTIClass::initialize(const MSRTTIClass *Parent,
+                                 const CXXBaseSpecifier *Specifier) {
+  Flags = HasHierarchyDescriptor;
+  if (!Parent) {
+    VirtualRoot = 0;
+    OffsetInVBase = 0;
+  } else {
+    if (Specifier->getAccessSpecifier() != AS_public)
+      Flags |= IsPrivate | IsPrivateOnPath;
+    if (Specifier->isVirtual()) {
+      Flags |= IsVirtual;
+      VirtualRoot = RD;
+      OffsetInVBase = 0;
+    } else {
+      if (Parent->Flags & IsPrivateOnPath)
+        Flags |= IsPrivateOnPath;
+      VirtualRoot = Parent->VirtualRoot;
+      OffsetInVBase = Parent->OffsetInVBase + RD->getASTContext()
+          .getASTRecordLayout(Parent->RD).getBaseClassOffset(RD).getQuantity();
+    }
+  }
+  NumBases = 0;
+  MSRTTIClass *Child = getFirstChild();
+  for (const CXXBaseSpecifier &Base : RD->bases()) {
+    NumBases += Child->initialize(this, &Base) + 1;
+    Child = getNextChild(Child);
+  }
+  return NumBases;
+}
+
+/// \brief An ephemeral helper class for building MS RTTI types.  It caches some
+/// calls to the module and information about the most derived class in a
+/// hierarchy.
+struct MSRTTIBuilder {
+  enum {
+    HasBranchingHierarchy = 1,
+    HasVirtualBranchingHierarchy = 2,
+    HasAmbiguousBases = 4
+  };
+
+  MSRTTIBuilder(CodeGenModule &CGM, const CXXRecordDecl *RD)
+      : CGM(CGM), Context(CGM.getContext()), VMContext(CGM.getLLVMContext()),
+        Module(CGM.getModule()), RD(RD), Linkage(CGM.getVTableLinkage(RD)),
+        Mangler(
+            cast<MicrosoftMangleContext>(CGM.getCXXABI().getMangleContext())) {}
+
+  llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes);
+  llvm::GlobalVariable *
+  getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes);
+  llvm::GlobalVariable *getClassHierarchyDescriptor();
+  llvm::GlobalVariable *getCompleteObjectLocator(const VPtrInfo *Info);
+
+  CodeGenModule &CGM;
+  ASTContext &Context;
+  llvm::LLVMContext &VMContext;
+  llvm::Module &Module;
+  const CXXRecordDecl *RD;
+  llvm::GlobalVariable::LinkageTypes Linkage;
+  MicrosoftMangleContext &Mangler;
+};
+
+} // namespace
+
+/// \brief Recursively serializes a class hierarchy in pre-order depth first
+/// order.
+static void serializeClassHierarchy(SmallVectorImpl<MSRTTIClass> &Classes,
+                                    const CXXRecordDecl *RD) {
+  Classes.push_back(MSRTTIClass(RD));
+  for (const CXXBaseSpecifier &Base : RD->bases())
+    serializeClassHierarchy(Classes, Base.getType()->getAsCXXRecordDecl());
+}
+
+/// \brief Find ambiguity among base classes.
+static void
+detectAmbiguousBases(SmallVectorImpl<MSRTTIClass> &Classes) {
+  llvm::SmallPtrSet<const CXXRecordDecl *, 8> VirtualBases;
+  llvm::SmallPtrSet<const CXXRecordDecl *, 8> UniqueBases;
+  llvm::SmallPtrSet<const CXXRecordDecl *, 8> AmbiguousBases;
+  for (MSRTTIClass *Class = &Classes.front(); Class <= &Classes.back();) {
+    if ((Class->Flags & MSRTTIClass::IsVirtual) &&
+        !VirtualBases.insert(Class->RD)) {
+      Class = MSRTTIClass::getNextChild(Class);
+      continue;
+    }
+    if (!UniqueBases.insert(Class->RD))
+      AmbiguousBases.insert(Class->RD);
+    Class++;
+  }
+  if (AmbiguousBases.empty())
+    return;
+  for (MSRTTIClass &Class : Classes)
+    if (AmbiguousBases.count(Class.RD))
+      Class.Flags |= MSRTTIClass::IsAmbiguous;
+}
+
+llvm::GlobalVariable *MSRTTIBuilder::getClassHierarchyDescriptor() {
+  SmallString<256> MangledName;
+  {
+    llvm::raw_svector_ostream Out(MangledName);
+    Mangler.mangleCXXRTTIClassHierarchyDescriptor(RD, Out);
+  }
+
+  // Check to see if we've already declared this ClassHierarchyDescriptor.
+  if (auto CHD = Module.getNamedGlobal(MangledName))
+    return CHD;
+
+  // Serialize the class hierarchy and initalize the CHD Fields.
+  SmallVector<MSRTTIClass, 8> Classes;
+  serializeClassHierarchy(Classes, RD);
+  Classes.front().initialize(/*Parent=*/0, /*Specifier=*/0);
+  detectAmbiguousBases(Classes);
+  int Flags = 0;
+  for (auto Class : Classes) {
+    if (Class.RD->getNumBases() > 1)
+      Flags |= HasBranchingHierarchy;
+    // Note: cl.exe does not calculate "HasAmbiguousBases" correctly.  We
+    // believe the field isn't actually used.
+    if (Class.Flags & MSRTTIClass::IsAmbiguous)
+      Flags |= HasAmbiguousBases;
+  }
+  if ((Flags & HasBranchingHierarchy) && RD->getNumVBases() != 0)
+    Flags |= HasVirtualBranchingHierarchy;
+  // These gep indices are used to get the address of the first element of the
+  // base class array.
+  llvm::Value *GEPIndices[] = {llvm::ConstantInt::get(CGM.IntTy, 0),
+                               llvm::ConstantInt::get(CGM.IntTy, 0)};
+
+  // Forward declare the class hierarchy descriptor
+  auto Type = getClassHierarchyDescriptorType(CGM);
+  auto CHD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+                                      /*Initializer=*/0, MangledName.c_str());
+
+  // Initialize the base class ClassHierarchyDescriptor.
+  llvm::Constant *Fields[] = {
+    llvm::ConstantInt::get(CGM.IntTy, 0), // Unknown
+    llvm::ConstantInt::get(CGM.IntTy, Flags),
+    llvm::ConstantInt::get(CGM.IntTy, Classes.size()),
+    llvm::ConstantExpr::getInBoundsGetElementPtr(
+        getBaseClassArray(Classes),
+        llvm::ArrayRef<llvm::Value *>(GEPIndices))};
+  CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+  return CHD;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
+  SmallString<256> MangledName;
+  {
+    llvm::raw_svector_ostream Out(MangledName);
+    Mangler.mangleCXXRTTIBaseClassArray(RD, Out);
+  }
+
+  // Foward declare the base class array.
+  // cl.exe pads the base class array with 1 (in 32 bit mode) or 4 (in 64 bit
+  // mode) bytes of padding.  We provide a pointer sized amount of padding by
+  // adding +1 to Classes.size().  The sections have pointer alignment and are
+  // marked pick-any so it shouldn't matter.
+  auto PtrType = getBaseClassDescriptorType(CGM)->getPointerTo();
+  auto ArrayType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
+  auto BCA = new llvm::GlobalVariable(Module, ArrayType,
+      /*Constant=*/true, Linkage, /*Initializer=*/0, MangledName.c_str());
+
+  // Initialize the BaseClassArray.
+  SmallVector<llvm::Constant *, 8> BaseClassArrayData;
+  for (MSRTTIClass &Class : Classes)
+    BaseClassArrayData.push_back(getBaseClassDescriptor(Class));
+  BaseClassArrayData.push_back(llvm::ConstantPointerNull::get(PtrType));
+  BCA->setInitializer(llvm::ConstantArray::get(ArrayType, BaseClassArrayData));
+  return BCA;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getBaseClassDescriptor(const MSRTTIClass &Class) {
+  // Compute the fields for the BaseClassDescriptor.  They are computed up front
+  // because they are mangled into the name of the object.
+  uint32_t OffsetInVBTable = 0;
+  int32_t VBPtrOffset = -1;
+  if (Class.VirtualRoot) {
+    auto &VTableContext = CGM.getMicrosoftVTableContext();
+    OffsetInVBTable = VTableContext.getVBTableIndex(RD, Class.VirtualRoot) * 4;
+    VBPtrOffset = Context.getASTRecordLayout(RD).getVBPtrOffset().getQuantity();
+  }
+
+  SmallString<256> MangledName;
+  {
+    llvm::raw_svector_ostream Out(MangledName);
+    Mangler.mangleCXXRTTIBaseClassDescriptor(Class.RD, Class.OffsetInVBase,
+                                             VBPtrOffset, OffsetInVBTable,
+                                             Class.Flags, Out);
+  }
+
+  // Check to see if we've already declared declared this object.
+  if (auto BCD = Module.getNamedGlobal(MangledName))
+    return BCD;
+
+  // Forward declare the base class descriptor.
+  auto Type = getBaseClassDescriptorType(CGM);
+  auto BCD = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+                                      /*Initializer=*/0, MangledName.c_str());
+
+  // Initialize the BaseClassDescriptor.
+  llvm::Constant *Fields[] = {
+    CGM.getMSTypeDescriptor(Context.getTypeDeclType(Class.RD)),
+    llvm::ConstantInt::get(CGM.IntTy, Class.NumBases),
+    llvm::ConstantInt::get(CGM.IntTy, Class.OffsetInVBase),
+    llvm::ConstantInt::get(CGM.IntTy, VBPtrOffset),
+    llvm::ConstantInt::get(CGM.IntTy, OffsetInVBTable),
+    llvm::ConstantInt::get(CGM.IntTy, Class.Flags),
+    MSRTTIBuilder(CGM, Class.RD).getClassHierarchyDescriptor()};
+  BCD->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+  return BCD;
+}
+
+llvm::GlobalVariable *
+MSRTTIBuilder::getCompleteObjectLocator(const VPtrInfo *Info) {
+  SmallString<256> MangledName;
+  {
+    llvm::raw_svector_ostream Out(MangledName);
+    Mangler.mangleCXXRTTICompleteObjectLocator(RD, Info->MangledPath, Out);
+  }
+
+  // Check to see if we've already computed this complete object locator.
+  if (auto COL = Module.getNamedGlobal(MangledName))
+    return COL;
+
+  // Compute the fields of the complete object locator.
+  int OffsetToTop = Info->FullOffsetInMDC.getQuantity();
+  int VFPtrOffset = 0;
+  // The offset includes the vtordisp if one exists.
+  if (const CXXRecordDecl *VBase = Info->getVBaseWithVPtr())
+    if (Context.getASTRecordLayout(RD)
+      .getVBaseOffsetsMap()
+      .find(VBase)
+      ->second.hasVtorDisp())
+      VFPtrOffset = Info->NonVirtualOffset.getQuantity() + 4;
+
+  // Forward declare the complete object locator.
+  llvm::StructType *Type = getCompleteObjectLocatorType(CGM);
+  auto COL = new llvm::GlobalVariable(Module, Type, /*Constant=*/true, Linkage,
+    /*Initializer=*/0, MangledName.c_str());
+
+  // Initialize the CompleteObjectLocator.
+  llvm::Constant *Fields[] = {
+    llvm::ConstantInt::get(CGM.IntTy, 0), // IsDeltaEncoded
+    llvm::ConstantInt::get(CGM.IntTy, OffsetToTop),
+    llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset),
+    CGM.getMSTypeDescriptor(Context.getTypeDeclType(RD)),
+    getClassHierarchyDescriptor()};
+  COL->setInitializer(llvm::ConstantStruct::get(Type, Fields));
+  return COL;
+}
+
+
+/// \brief Gets a TypeDescriptor.  Returns a llvm::Constant * rather than a
+/// llvm::GlobalVariable * because different type descriptors have different
+/// types, and need to be abstracted.  They are abstracting by casting the
+/// address to an Int8PtrTy.
+llvm::Constant *CodeGenModule::getMSTypeDescriptor(QualType Type) {
+  auto &Mangler(cast<MicrosoftMangleContext>(getCXXABI().getMangleContext()));
+  SmallString<256> MangledName, TypeInfoString;
+  {
+    llvm::raw_svector_ostream Out(MangledName);
+    Mangler.mangleCXXRTTI(Type, Out);
+  }
+
+  // Check to see if we've already declared this TypeDescriptor.
+  if (auto TypeDescriptor = getModule().getNamedGlobal(MangledName))
+    return llvm::ConstantExpr::getBitCast(TypeDescriptor, Int8PtrTy);
+
+  // Compute the fields for the TypeDescriptor.
+  {
+    llvm::raw_svector_ostream Out(TypeInfoString);
+    Mangler.mangleCXXRTTIName(Type, Out);
+  }
+
+  // Declare and initialize the TypeDescriptor.
+  llvm::Constant *Fields[] = {
+    getTypeInfoVTable(*this),                  // VFPtr
+    llvm::ConstantPointerNull::get(Int8PtrTy), // Runtime data
+    llvm::ConstantDataArray::getString(VMContext, TypeInfoString)};
+  auto TypeDescriptorType = getTypeDescriptorType(*this, TypeInfoString);
+  return llvm::ConstantExpr::getBitCast(
+      new llvm::GlobalVariable(
+          getModule(), TypeDescriptorType, /*Constant=*/false,
+          getTypeInfoLinkage(Type),
+          llvm::ConstantStruct::get(TypeDescriptorType, Fields),
+          MangledName.c_str()),
+      Int8PtrTy);
+}
+
+llvm::GlobalVariable *
+CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD,
+                                          const VPtrInfo *Info) {
+  return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info);
+}

Added: cfe/trunk/test/CodeGenCXX/microsoft-abi-rtti.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-rtti.cpp?rev=209523&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-rtti.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-rtti.cpp Fri May 23 11:07:43 2014
@@ -0,0 +1,146 @@
+// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 2>/dev/null %s | FileCheck %s
+
+struct N {};
+struct M : private N {};
+struct X { virtual void f() {} };
+class Z { virtual void f() {} };
+class V : public X { virtual void f() {} };
+class W : M, virtual V { public: virtual void f() {} };
+class Y : Z, W, virtual V { public: virtual void g() {} } y;
+
+struct A {};
+struct B : A {};
+struct C : B { virtual void f() {} } c;
+
+struct X1 { virtual void f() {} };
+struct V1 : X1 {};
+struct W1 : virtual V1 {};
+struct Y1 : W1, virtual V1 {} y1;
+
+struct A1 { virtual void f() {} };
+struct B1 : virtual A1 { virtual void f() {} B1() {} } b1;
+
+struct Z2 { virtual void f() {} };
+struct Y2 { virtual void f() {} };
+struct A2 : Z2, Y2 {};
+struct B2 : virtual A2 { B2() {} virtual void f() {} } b2;
+
+// CHECK: @"\01??_R4B2@@6BZ2@@@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUB2@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3B2@@8" }
+// CHECK: @"\01??_R0?AUB2@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB2@@\00" }
+// CHECK: @"\01??_R3B2@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 3, i32 4, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([5 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2B2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2B2@@8" = linkonce_odr constant [5 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@B2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3FA at A2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3EA at Z2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13A at 3EA@Y2@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@B2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUB2@@@8" to i8*), i32 3, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3B2@@8" }
+// CHECK: @"\01??_R1A at A@3FA at A2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 0, i32 4, i32 80, %MSRTTIClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R0?AUA2@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA2@@\00" }
+// CHECK: @"\01??_R3A2@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 1, i32 3, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([4 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2A2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2A2@@8" = linkonce_odr constant [4 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@A2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@Z2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A at EA@Y2@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@A2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUA2@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R1A@?0A at EA@Z2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Z2@@8" }
+// CHECK: @"\01??_R0?AUZ2@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUZ2@@\00" }
+// CHECK: @"\01??_R3Z2@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2Z2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Z2@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@Z2@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R13?0A at EA@Y2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R0?AUY2@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY2@@\00" }
+// CHECK: @"\01??_R3Y2@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2Y2@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Y2@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@Y2@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@Y2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R1A at A@3EA at Z2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUZ2@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Z2@@8" }
+// CHECK: @"\01??_R13A at 3EA@Y2@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUY2@@@8" to i8*), i32 0, i32 4, i32 0, i32 4, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R4B2@@6BY2@@@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 12, i32 8, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUB2@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3B2@@8" }
+// CHECK: @"\01??_R4A2@@6BZ2@@@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUA2@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R4A2@@6BY2@@@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUA2@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3A2@@8" }
+// CHECK: @"\01??_R4Y2@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUY2@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y2@@8" }
+// CHECK: @"\01??_R4Z2@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUZ2@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3Z2@@8" }
+// CHECK: @"\01??_R4B1@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 8, i32 4, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUB1@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3B1@@8" }
+// CHECK: @"\01??_R0?AUB1@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUB1@@\00" }
+// CHECK: @"\01??_R3B1@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 2, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([3 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2B1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2B1@@8" = linkonce_odr constant [3 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@B1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3FA at A1@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@B1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUB1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3B1@@8" }
+// CHECK: @"\01??_R1A at A@3FA at A1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 80, %MSRTTIClassHierarchyDescriptor* @"\01??_R3A1@@8" }
+// CHECK: @"\01??_R0?AUA1@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUA1@@\00" }
+// CHECK: @"\01??_R3A1@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2A1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2A1@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@A1@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@A1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUA1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3A1@@8" }
+// CHECK: @"\01??_R4A1@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUA1@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3A1@@8" }
+// CHECK: @"\01??_R4Y1@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUY1@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y1@@8" }
+// CHECK: @"\01??_R0?AUY1@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUY1@@\00" }
+// CHECK: @"\01??_R3Y1@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 3, i32 6, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([7 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2Y1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Y1@@8" = linkonce_odr constant [7 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@Y1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@W1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3FA at V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3EA at X1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3FA at V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3EA at X1@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@Y1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUY1@@@8" to i8*), i32 5, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y1@@8" }
+// CHECK: @"\01??_R1A@?0A at EA@W1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUW1@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3W1@@8" }
+// CHECK: @"\01??_R0?AUW1@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUW1@@\00" }
+// CHECK: @"\01??_R3W1@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 3, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([4 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2W1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2W1@@8" = linkonce_odr constant [4 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@W1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3FA at V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3EA at X1@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A at A@3FA at V1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 80, %MSRTTIClassHierarchyDescriptor* @"\01??_R3V1@@8" }
+// CHECK: @"\01??_R0?AUV1@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUV1@@\00" }
+// CHECK: @"\01??_R3V1@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 2, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([3 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2V1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2V1@@8" = linkonce_odr constant [3 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@X1@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@V1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUV1@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3V1@@8" }
+// CHECK: @"\01??_R1A@?0A at EA@X1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3X1@@8" }
+// CHECK: @"\01??_R0?AUX1@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\08" { i8** @"\01??_7type_info@@6B@", i8* null, [9 x i8] c".?AUX1@@\00" }
+// CHECK: @"\01??_R3X1@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2X1@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2X1@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@X1@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A at A@3EA at X1@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUX1@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3X1@@8" }
+// CHECK: @"\01??_R4W1@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUW1@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3W1@@8" }
+// CHECK: @"\01??_R4V1@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUV1@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3V1@@8" }
+// CHECK: @"\01??_R4X1@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\08"* @"\01??_R0?AUX1@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3X1@@8" }
+// CHECK: @"\01??_R4C@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUC@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3C@@8" }
+// CHECK: @"\01??_R0?AUC@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUC@@\00" }
+// CHECK: @"\01??_R3C@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 3, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([4 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2C@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2C@@8" = linkonce_odr constant [4 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@C@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A at EA@B@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A at EA@A@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@C@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUC@@@8" to i8*), i32 2, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3C@@8" }
+// CHECK: @"\01??_R13?0A at EA@B@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3B@@8" }
+// CHECK: @"\01??_R0?AUB@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUB@@\00" }
+// CHECK: @"\01??_R3B@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 2, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([3 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2B@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2B@@8" = linkonce_odr constant [3 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@B@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@A@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@B@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUB@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3B@@8" }
+// CHECK: @"\01??_R1A@?0A at EA@A@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3A@@8" }
+// CHECK: @"\01??_R0?AUA@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUA@@\00" }
+// CHECK: @"\01??_R3A@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2A@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2A@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@A@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R13?0A at EA@A@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUA@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3A@@8" }
+// CHECK: @"\01??_R4Y@@6BZ@@@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVY@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y@@8" }
+// CHECK: @"\01??_R0?AVY@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVY@@\00" }
+// CHECK: @"\01??_R3Y@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 3, i32 9, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([10 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2Y@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Y@@8" = linkonce_odr constant [10 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@Y@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EN@Z@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A at EN@W@@8", %MSRTTIBaseClassDescriptor* @"\01??_R17?0A at EN@M@@8", %MSRTTIBaseClassDescriptor* @"\01??_R17?0A at EN@N@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at 33FN@V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at 33EJ@X@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at 33FN@V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at 33EJ@X@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@Y@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVY@@@8" to i8*), i32 8, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y@@8" }
+// CHECK: @"\01??_R1A@?0A at EN@Z@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Z@@8" }
+// CHECK: @"\01??_R0?AVZ@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVZ@@\00" }
+// CHECK: @"\01??_R3Z@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2Z@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2Z@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@Z@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@Z@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVZ@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3Z@@8" }
+// CHECK: @"\01??_R13?0A at EN@W@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 4, i32 -1, i32 0, i32 77, %MSRTTIClassHierarchyDescriptor* @"\01??_R3W@@8" }
+// CHECK: @"\01??_R0?AVW@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVW@@\00" }
+// CHECK: @"\01??_R3W@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 3, i32 5, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([6 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2W@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2W@@8" = linkonce_odr constant [6 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@W@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A at EN@M@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A at EN@N@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3FN at V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A at A@3EJ at X@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@W@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVW@@@8" to i8*), i32 4, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3W@@8" }
+// CHECK: @"\01??_R13?0A at EN@M@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 4, i32 -1, i32 0, i32 77, %MSRTTIClassHierarchyDescriptor* @"\01??_R3M@@8" }
+// CHECK: @"\01??_R0?AUM@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUM@@\00" }
+// CHECK: @"\01??_R3M@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 2, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([3 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2M@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2M@@8" = linkonce_odr constant [3 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@M@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EN@N@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@M@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3M@@8" }
+// CHECK: @"\01??_R1A@?0A at EN@N@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 77, %MSRTTIClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R0?AUN@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUN@@\00" }
+// CHECK: @"\01??_R3N@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2N@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2N@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@N@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@N@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R13?0A at EN@N@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 4, i32 -1, i32 0, i32 77, %MSRTTIClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R1A at A@3FN at V@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 0, i32 4, i32 93, %MSRTTIClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R0?AVV@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AVV@@\00" }
+// CHECK: @"\01??_R3V@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 2, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([3 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2V@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2V@@8" = linkonce_odr constant [3 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@X@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A@?0A at EA@V@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R1A@?0A at EA@X@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 -1, i32 0, i32 64, %MSRTTIClassHierarchyDescriptor* @"\01??_R3X@@8" }
+// CHECK: @"\01??_R0?AUX@@@8" = linkonce_odr global %"MSRTTITypeDescriptor\07" { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUX@@\00" }
+// CHECK: @"\01??_R3X@@8" = linkonce_odr constant %MSRTTIClassHierarchyDescriptor { i32 0, i32 0, i32 1, %MSRTTIBaseClassDescriptor** getelementptr inbounds ([2 x %MSRTTIBaseClassDescriptor*]* @"\01??_R2X@@8", i32 0, i32 0) }
+// CHECK: @"\01??_R2X@@8" = linkonce_odr constant [2 x %MSRTTIBaseClassDescriptor*] [%MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A at EA@X@@8", %MSRTTIBaseClassDescriptor* null]
+// CHECK: @"\01??_R1A at A@3EJ at X@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 0, i32 4, i32 73, %MSRTTIClassHierarchyDescriptor* @"\01??_R3X@@8" }
+// CHECK: @"\01??_R17?0A at EN@M@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUM@@@8" to i8*), i32 1, i32 8, i32 -1, i32 0, i32 77, %MSRTTIClassHierarchyDescriptor* @"\01??_R3M@@8" }
+// CHECK: @"\01??_R17?0A at EN@N@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUN@@@8" to i8*), i32 0, i32 8, i32 -1, i32 0, i32 77, %MSRTTIClassHierarchyDescriptor* @"\01??_R3N@@8" }
+// CHECK: @"\01??_R1A at 33FN@V@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVV@@@8" to i8*), i32 1, i32 0, i32 4, i32 4, i32 93, %MSRTTIClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R1A at 33EJ@X@@8" = linkonce_odr constant %MSRTTIBaseClassDescriptor { i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUX@@@8" to i8*), i32 0, i32 0, i32 4, i32 4, i32 73, %MSRTTIClassHierarchyDescriptor* @"\01??_R3X@@8" }
+// CHECK: @"\01??_R4Y@@6BW@@@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 8, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVY@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3Y@@8" }
+// CHECK: @"\01??_R4W@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 4, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVW@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3W@@8" }
+// CHECK: @"\01??_R4Z@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVZ@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3Z@@8" }
+// CHECK: @"\01??_R4V@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AVV@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3V@@8" }
+// CHECK: @"\01??_R4X@@6B@" = linkonce_odr constant %MSRTTICompleteObjectLocator { i32 0, i32 0, i32 0, i8* bitcast (%"MSRTTITypeDescriptor\07"* @"\01??_R0?AUX@@@8" to i8*), %MSRTTIClassHierarchyDescriptor* @"\01??_R3X@@8" }





More information about the cfe-commits mailing list