forked from OSchip/llvm-project
[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 llvm-svn: 209523
This commit is contained in:
parent
2be4a28297
commit
5c2b4ea662
|
@ -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,
|
||||
|
|
|
@ -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::mangleCXXRTTIName(QualType T,
|
|||
}
|
||||
|
||||
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::mangleCXXRTTIBaseClassDescriptor(
|
|||
Mangler.mangleNumber(VBTableOffset);
|
||||
Mangler.mangleNumber(Flags);
|
||||
Mangler.mangleName(Derived);
|
||||
Mangler.getStream() << "@8";
|
||||
Mangler.getStream() << "8";
|
||||
}
|
||||
|
||||
void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray(
|
||||
|
@ -2275,7 +2275,7 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIBaseClassArray(
|
|||
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::mangleCXXRTTIClassHierarchyDescriptor(
|
|||
MicrosoftCXXNameMangler Mangler(*this, Out);
|
||||
Mangler.getStream() << "\01??_R3";
|
||||
Mangler.mangleName(Derived);
|
||||
Mangler.getStream() << "@8";
|
||||
Mangler.getStream() << "8";
|
||||
}
|
||||
|
||||
void MicrosoftMangleContextImpl::mangleCXXRTTICompleteObjectLocator(
|
||||
|
|
|
@ -2086,7 +2086,7 @@ LValue CodeGenFunction::EmitPredefinedLValue(const PredefinedExpr *E) {
|
|||
/// 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::EmitCheckTypeDescriptor(QualType T) {
|
|||
GV->setUnnamedAddr(true);
|
||||
|
||||
// Remember the descriptor for this type.
|
||||
CGM.setTypeDescriptor(T, GV);
|
||||
CGM.setTypeDescriptorInMap(T, GV);
|
||||
|
||||
return GV;
|
||||
}
|
||||
|
|
|
@ -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 Ty,
|
|||
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(QualType Ty) {
|
|||
|
||||
/// 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, QualType Ty) {
|
|||
|
||||
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, QualType Ty) {
|
|||
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(const CXXRecordDecl *RD) {
|
|||
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(const Type *Ty) {
|
|||
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::BuildTypeInfo(QualType Ty, bool Force) {
|
|||
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(Qualifiers Quals) {
|
|||
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::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
|
|||
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 ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
|
|||
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 ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
|
|||
/// 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(const CXXRecordDecl *RD) {
|
|||
// };
|
||||
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(const CXXRecordDecl *RD) {
|
|||
|
||||
/// 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(QualType PointeeTy) {
|
|||
// __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::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
|
|||
// __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::GetAddrOfRTTIDescriptor(QualType Ty,
|
|||
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() {
|
||||
|
|
|
@ -60,6 +60,7 @@ add_clang_library(clangCodeGen
|
|||
CodeGenTypes.cpp
|
||||
ItaniumCXXABI.cpp
|
||||
MicrosoftCXXABI.cpp
|
||||
MicrosoftRTTI.cpp
|
||||
ModuleBuilder.cpp
|
||||
TargetInfo.cpp
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -897,14 +897,15 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
|
|||
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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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@EA@B2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3FA@A2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3EA@Z2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13A@3EA@Y2@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@A@3FA@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@EA@A2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A@EA@Z2@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A@EA@Y2@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@Z2@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R13?0A@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@EA@Y2@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@A@3EA@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@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@EA@B1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3FA@A1@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@A@3FA@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@EA@A1@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@EA@Y1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A@EA@W1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@W1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3FA@V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3EA@X1@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@A@3FA@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@EA@V1@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A@EA@X1@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@X1@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@A@3EA@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@EA@C@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A@EA@B@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A@EA@A@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@B@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A@EA@A@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@A@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R13?0A@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@EA@Y@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A@EN@Z@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A@EN@W@@8", %MSRTTIBaseClassDescriptor* @"\01??_R17?0A@EN@M@@8", %MSRTTIBaseClassDescriptor* @"\01??_R17?0A@EN@N@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@33FN@V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@33EJ@X@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@Z@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@W@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A@EN@M@@8", %MSRTTIBaseClassDescriptor* @"\01??_R13?0A@EN@N@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3FN@V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@A@3EJ@X@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@M@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A@EN@N@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@N@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@A@3FN@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@EA@V@@8", %MSRTTIBaseClassDescriptor* @"\01??_R1A@?0A@EA@X@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@?0A@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@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@EA@X@@8", %MSRTTIBaseClassDescriptor* null]
|
||||
// CHECK: @"\01??_R1A@A@3EJ@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@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@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@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@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" }
|
Loading…
Reference in New Issue