From e2cb8d198f54b84187419a23b3f3e1d05015e5e7 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 7 Jul 2014 06:20:47 +0000 Subject: [PATCH] CodeGen: Refactor RTTI emission Let's not expose ABI specific minutia inside of CodeGenModule and Type. Instead, let's abstract it through CXXABI. This gets rid of: CodeGenModule::getCompleteObjectLocator, CodeGenModule::EmitFundamentalTypeDescriptor{s,}, CodeGenModule::getMSTypeDescriptor, CodeGenModule::getMSCompleteObjectLocator, CGCXXABI::shouldRTTIBeUnique, CGCXXABI::classifyRTTIUniqueness. CGRTTI was *almost* entirely centered around providing Itanium-style RTTI information. Instead of providing interfaces that only it consumes, move it to the ItaniumCXXABI implementation file. This allows it to have access to Itanium-specific implementation details without providing useless expansion points for the Microsoft ABI side. Differential Revision: http://reviews.llvm.org/D4261 llvm-svn: 212435 --- clang/lib/CodeGen/CGCXXABI.cpp | 28 - clang/lib/CodeGen/CGCXXABI.h | 32 +- clang/lib/CodeGen/CGRTTI.cpp | 998 ------------------------------- clang/lib/CodeGen/CMakeLists.txt | 2 - clang/lib/CodeGen/CodeGenModule.cpp | 16 + clang/lib/CodeGen/CodeGenModule.h | 9 - clang/lib/CodeGen/ItaniumCXXABI.cpp | 1032 ++++++++++++++++++++++++++++++++- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 513 +++++++++++++++- clang/lib/CodeGen/MicrosoftRTTI.cpp | 529 ----------------- 9 files changed, 1560 insertions(+), 1599 deletions(-) delete mode 100644 clang/lib/CodeGen/CGRTTI.cpp delete mode 100644 clang/lib/CodeGen/MicrosoftRTTI.cpp diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp index ee65d77..55ddd66 100644 --- a/clang/lib/CodeGen/CGCXXABI.cpp +++ b/clang/lib/CodeGen/CGCXXABI.cpp @@ -325,31 +325,3 @@ LValue CGCXXABI::EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) { return false; } - -/// What sort of uniqueness rules should we use for the RTTI for the -/// given type? -CGCXXABI::RTTIUniquenessKind -CGCXXABI::classifyRTTIUniqueness(QualType CanTy, - llvm::GlobalValue::LinkageTypes Linkage) { - if (shouldRTTIBeUnique()) - return RUK_Unique; - - // It's only necessary for linkonce_odr or weak_odr linkage. - if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage && - Linkage != llvm::GlobalValue::WeakODRLinkage) - return RUK_Unique; - - // It's only necessary with default visibility. - if (CanTy->getVisibility() != DefaultVisibility) - return RUK_Unique; - - // If we're not required to publish this symbol, hide it. - if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage) - return RUK_NonUniqueHidden; - - // If we're required to publish this symbol, as we might be under an - // explicit instantiation, leave it with default visibility but - // enable string-comparisons. - assert(Linkage == llvm::GlobalValue::WeakODRLinkage); - return RUK_NonUniqueVisible; -} diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 0a31d2a..b49c68a4 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -207,6 +207,8 @@ public: llvm::Value *ptr, QualType type) = 0; + virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0; + virtual bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) = 0; virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0; @@ -516,36 +518,6 @@ public: virtual LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD, QualType LValType); - - /**************************** RTTI Uniqueness ******************************/ - -protected: - /// Returns true if the ABI requires RTTI type_info objects to be unique - /// across a program. - virtual bool shouldRTTIBeUnique() { return true; } - -public: - /// What sort of unique-RTTI behavior should we use? - enum RTTIUniquenessKind { - /// We are guaranteeing, or need to guarantee, that the RTTI string - /// is unique. - RUK_Unique, - - /// We are not guaranteeing uniqueness for the RTTI string, so we - /// can demote to hidden visibility but must use string comparisons. - RUK_NonUniqueHidden, - - /// We are not guaranteeing uniqueness for the RTTI string, so we - /// have to use string comparisons, but we also have to emit it with - /// non-hidden visibility. - RUK_NonUniqueVisible - }; - - /// Return the required visibility status for the given type and linkage in - /// the current ABI. - RTTIUniquenessKind - classifyRTTIUniqueness(QualType CanTy, - llvm::GlobalValue::LinkageTypes Linkage); }; // Create an instance of a C++ ABI class: diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp deleted file mode 100644 index 4ca315c..0000000 --- a/clang/lib/CodeGen/CGRTTI.cpp +++ /dev/null @@ -1,998 +0,0 @@ -//===--- 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; - -namespace { -class ItaniumRTTIBuilder { - CodeGenModule &CGM; // Per-module state. - llvm::LLVMContext &VMContext; - - /// Fields - The fields of the RTTI descriptor currently being built. - SmallVector Fields; - - /// GetAddrOfTypeName - Returns the mangled type name of the given type. - llvm::GlobalVariable * - GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage); - - /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI - /// descriptor of the given type. - llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); - - /// BuildVTablePointer - Build the vtable pointer for the given type. - void BuildVTablePointer(const Type *Ty); - - /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single - /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b. - void BuildSIClassTypeInfo(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 BuildVMIClassTypeInfo(const CXXRecordDecl *RD); - - /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used - /// for pointer types. - void BuildPointerTypeInfo(QualType PointeeTy); - - /// BuildObjCObjectTypeInfo - Build the appropriate kind of - /// type_info for an object type. - void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty); - - /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info - /// struct, used for member pointer types. - void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty); - -public: - ItaniumRTTIBuilder(CodeGenModule &CGM) : CGM(CGM), - VMContext(CGM.getModule().getContext()) { } - - // Pointer type info flags. - enum { - /// PTI_Const - Type has const qualifier. - PTI_Const = 0x1, - - /// PTI_Volatile - Type has volatile qualifier. - PTI_Volatile = 0x2, - - /// PTI_Restrict - Type has restrict qualifier. - PTI_Restrict = 0x4, - - /// PTI_Incomplete - Type is incomplete. - PTI_Incomplete = 0x8, - - /// PTI_ContainingClassIncomplete - Containing class is incomplete. - /// (in pointer to member). - PTI_ContainingClassIncomplete = 0x10 - }; - - // VMI type info flags. - enum { - /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance. - VMI_NonDiamondRepeat = 0x1, - - /// VMI_DiamondShaped - Class is diamond shaped. - VMI_DiamondShaped = 0x2 - }; - - // Base class type info flags. - enum { - /// BCTI_Virtual - Base class is virtual. - BCTI_Virtual = 0x1, - - /// BCTI_Public - Base class is public. - BCTI_Public = 0x2 - }; - - /// BuildTypeInfo - Build the RTTI type info struct for the given type. - /// - /// \param Force - true to force the creation of this RTTI value - llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false); -}; -} - -llvm::GlobalVariable * -ItaniumRTTIBuilder::GetAddrOfTypeName(QualType Ty, - llvm::GlobalVariable::LinkageTypes Linkage) { - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out); - Out.flush(); - StringRef Name = OutName.str(); - - // We know that the mangled name of the type starts at index 4 of the - // mangled name of the typename, so we can just index into it in order to - // get the mangled name of the type. - llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext, - Name.substr(4)); - - llvm::GlobalVariable *GV = - CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage); - - GV->setInitializer(Init); - - return GV; -} - -llvm::Constant * -ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { - // Mangle the RTTI name. - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); - Out.flush(); - StringRef Name = OutName.str(); - - // Look for an existing global. - llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name); - - if (!GV) { - // Create a new global variable. - GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, - /*Constant=*/true, - llvm::GlobalValue::ExternalLinkage, nullptr, - Name); - } - - return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); -} - -/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type -/// info for that type is defined in the standard library. -static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { - // Itanium C++ ABI 2.9.2: - // Basic type information (e.g. for "int", "bool", etc.) will be kept in - // the run-time support library. Specifically, the run-time support - // library should contain type_info objects for the types X, X* and - // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char, - // unsigned char, signed char, short, unsigned short, int, unsigned int, - // long, unsigned long, long long, unsigned long long, float, double, - // long double, char16_t, char32_t, and the IEEE 754r decimal and - // half-precision floating point types. - switch (Ty->getKind()) { - case BuiltinType::Void: - case BuiltinType::NullPtr: - case BuiltinType::Bool: - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - case BuiltinType::Char_U: - case BuiltinType::Char_S: - case BuiltinType::UChar: - case BuiltinType::SChar: - case BuiltinType::Short: - case BuiltinType::UShort: - case BuiltinType::Int: - case BuiltinType::UInt: - case BuiltinType::Long: - case BuiltinType::ULong: - case BuiltinType::LongLong: - case BuiltinType::ULongLong: - case BuiltinType::Half: - case BuiltinType::Float: - case BuiltinType::Double: - case BuiltinType::LongDouble: - case BuiltinType::Char16: - case BuiltinType::Char32: - case BuiltinType::Int128: - case BuiltinType::UInt128: - case BuiltinType::OCLImage1d: - case BuiltinType::OCLImage1dArray: - case BuiltinType::OCLImage1dBuffer: - case BuiltinType::OCLImage2d: - case BuiltinType::OCLImage2dArray: - case BuiltinType::OCLImage3d: - case BuiltinType::OCLSampler: - case BuiltinType::OCLEvent: - return true; - - case BuiltinType::Dependent: -#define BUILTIN_TYPE(Id, SingletonId) -#define PLACEHOLDER_TYPE(Id, SingletonId) \ - case BuiltinType::Id: -#include "clang/AST/BuiltinTypes.def" - llvm_unreachable("asking for RRTI for a placeholder type!"); - - case BuiltinType::ObjCId: - case BuiltinType::ObjCClass: - case BuiltinType::ObjCSel: - llvm_unreachable("FIXME: Objective-C types are unsupported!"); - } - - llvm_unreachable("Invalid BuiltinType Kind!"); -} - -static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { - QualType PointeeTy = PointerTy->getPointeeType(); - const BuiltinType *BuiltinTy = dyn_cast(PointeeTy); - if (!BuiltinTy) - return false; - - // Check the qualifiers. - Qualifiers Quals = PointeeTy.getQualifiers(); - Quals.removeConst(); - - if (!Quals.empty()) - return false; - - return TypeInfoIsInStandardLibrary(BuiltinTy); -} - -/// IsStandardLibraryRTTIDescriptor - Returns whether the type -/// information for the given type exists in the standard library. -static bool IsStandardLibraryRTTIDescriptor(QualType Ty) { - // Type info for builtin types is defined in the standard library. - if (const BuiltinType *BuiltinTy = dyn_cast(Ty)) - return TypeInfoIsInStandardLibrary(BuiltinTy); - - // Type info for some pointer types to builtin types is defined in the - // standard library. - if (const PointerType *PointerTy = dyn_cast(Ty)) - return TypeInfoIsInStandardLibrary(PointerTy); - - return false; -} - -/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for -/// the given type exists somewhere else, and that we should not emit the type -/// information in this translation unit. Assumes that it is not a -/// standard-library type. -static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, - QualType Ty) { - ASTContext &Context = CGM.getContext(); - - // If RTTI is disabled, assume it might be disabled in the - // translation unit that defines any potential key function, too. - if (!Context.getLangOpts().RTTI) return false; - - if (const RecordType *RecordTy = dyn_cast(Ty)) { - const CXXRecordDecl *RD = cast(RecordTy->getDecl()); - if (!RD->hasDefinition()) - return false; - - if (!RD->isDynamicClass()) - return false; - - // FIXME: this may need to be reconsidered if the key function - // changes. - return CGM.getVTables().isVTableExternal(RD); - } - - return false; -} - -/// IsIncompleteClassType - Returns whether the given record type is incomplete. -static bool IsIncompleteClassType(const RecordType *RecordTy) { - return !RecordTy->getDecl()->isCompleteDefinition(); -} - -/// ContainsIncompleteClassType - Returns whether the given type contains an -/// incomplete class type. This is true if -/// -/// * The given type is an incomplete class type. -/// * The given type is a pointer type whose pointee type contains an -/// incomplete class type. -/// * The given type is a member pointer type whose class is an incomplete -/// class type. -/// * The given type is a member pointer type whoise pointee type contains an -/// incomplete class type. -/// is an indirect or direct pointer to an incomplete class type. -static bool ContainsIncompleteClassType(QualType Ty) { - if (const RecordType *RecordTy = dyn_cast(Ty)) { - if (IsIncompleteClassType(RecordTy)) - return true; - } - - if (const PointerType *PointerTy = dyn_cast(Ty)) - return ContainsIncompleteClassType(PointerTy->getPointeeType()); - - if (const MemberPointerType *MemberPointerTy = - dyn_cast(Ty)) { - // Check if the class type is incomplete. - const RecordType *ClassType = cast(MemberPointerTy->getClass()); - if (IsIncompleteClassType(ClassType)) - return true; - - return ContainsIncompleteClassType(MemberPointerTy->getPointeeType()); - } - - return false; -} - -/// getTypeInfoLinkage - Return the linkage that the type info and type info -/// name constants should have for the given type. -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 - // incomplete class type must be prevented from resolving to the - // corresponding type_info structs for the complete class type, possibly - // by making them local static objects. Finally, a dummy class RTTI is - // generated for the incomplete type that will not resolve to the final - // complete class RTTI (because the latter need not exist), possibly by - // making it a local static object. - if (ContainsIncompleteClassType(Ty)) - return llvm::GlobalValue::InternalLinkage; - - switch (Ty->getLinkage()) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: - return llvm::GlobalValue::InternalLinkage; - - case VisibleNoLinkage: - case ExternalLinkage: - 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; - } - - if (const RecordType *Record = dyn_cast(Ty)) { - const CXXRecordDecl *RD = cast(Record->getDecl()); - if (RD->hasAttr()) - return llvm::GlobalValue::WeakODRLinkage; - if (RD->isDynamicClass()) - return getVTableLinkage(RD); - } - - return llvm::GlobalValue::LinkOnceODRLinkage; - } - - llvm_unreachable("Invalid linkage!"); -} - -// CanUseSingleInheritance - Return whether the given record decl has a "single, -// public, non-virtual base at offset zero (i.e. the derived class is dynamic -// iff the base is)", according to Itanium C++ ABI, 2.95p6b. -static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { - // Check the number of bases. - if (RD->getNumBases() != 1) - return false; - - // Get the base. - CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(); - - // Check that the base is not virtual. - if (Base->isVirtual()) - return false; - - // Check that the base is public. - if (Base->getAccessSpecifier() != AS_public) - return false; - - // Check that the class is dynamic iff the base is. - const CXXRecordDecl *BaseDecl = - cast(Base->getType()->getAs()->getDecl()); - if (!BaseDecl->isEmpty() && - BaseDecl->isDynamicClass() != RD->isDynamicClass()) - return false; - - return true; -} - -void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { - // abi::__class_type_info. - static const char * const ClassTypeInfo = - "_ZTVN10__cxxabiv117__class_type_infoE"; - // abi::__si_class_type_info. - static const char * const SIClassTypeInfo = - "_ZTVN10__cxxabiv120__si_class_type_infoE"; - // abi::__vmi_class_type_info. - static const char * const VMIClassTypeInfo = - "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; - - const char *VTableName = nullptr; - - switch (Ty->getTypeClass()) { -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#include "clang/AST/TypeNodes.def" - llvm_unreachable("Non-canonical and dependent types shouldn't get here"); - - case Type::LValueReference: - case Type::RValueReference: - llvm_unreachable("References shouldn't get here"); - - case Type::Auto: - llvm_unreachable("Undeduced auto type shouldn't get here"); - - case Type::Builtin: - // GCC treats vector and complex types as fundamental types. - case Type::Vector: - case Type::ExtVector: - case Type::Complex: - case Type::Atomic: - // FIXME: GCC treats block pointers as fundamental types?! - case Type::BlockPointer: - // abi::__fundamental_type_info. - VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE"; - break; - - case Type::ConstantArray: - case Type::IncompleteArray: - case Type::VariableArray: - // abi::__array_type_info. - VTableName = "_ZTVN10__cxxabiv117__array_type_infoE"; - break; - - case Type::FunctionNoProto: - case Type::FunctionProto: - // abi::__function_type_info. - VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; - break; - - case Type::Enum: - // abi::__enum_type_info. - VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; - break; - - case Type::Record: { - const CXXRecordDecl *RD = - cast(cast(Ty)->getDecl()); - - if (!RD->hasDefinition() || !RD->getNumBases()) { - VTableName = ClassTypeInfo; - } else if (CanUseSingleInheritance(RD)) { - VTableName = SIClassTypeInfo; - } else { - VTableName = VMIClassTypeInfo; - } - - break; - } - - case Type::ObjCObject: - // Ignore protocol qualifiers. - Ty = cast(Ty)->getBaseType().getTypePtr(); - - // Handle id and Class. - if (isa(Ty)) { - VTableName = ClassTypeInfo; - break; - } - - assert(isa(Ty)); - // Fall through. - - case Type::ObjCInterface: - if (cast(Ty)->getDecl()->getSuperClass()) { - VTableName = SIClassTypeInfo; - } else { - VTableName = ClassTypeInfo; - } - break; - - case Type::ObjCObjectPointer: - case Type::Pointer: - // abi::__pointer_type_info. - VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; - break; - - case Type::MemberPointer: - // abi::__pointer_to_member_type_info. - VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; - break; - } - - llvm::Constant *VTable = - CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy); - - llvm::Type *PtrDiffTy = - CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); - - // The vtable address point is 2. - llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2); - VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two); - VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy); - - Fields.push_back(VTable); -} - -llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { - // We want to operate on the canonical type. - Ty = CGM.getContext().getCanonicalType(Ty); - - // Check if we've already emitted an RTTI descriptor for this type. - SmallString<256> OutName; - llvm::raw_svector_ostream Out(OutName); - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); - Out.flush(); - StringRef Name = OutName.str(); - - llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); - if (OldGV && !OldGV->isDeclaration()) { - assert(!OldGV->hasAvailableExternallyLinkage() && - "available_externally typeinfos not yet implemented"); - - return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy); - } - - // Check if there is already an external RTTI descriptor for this type. - bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty); - if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty))) - return GetAddrOfExternalRTTIDescriptor(Ty); - - // Emit the standard library with external linkage. - llvm::GlobalVariable::LinkageTypes Linkage; - if (IsStdLib) - Linkage = llvm::GlobalValue::ExternalLinkage; - else - Linkage = CGM.getTypeInfoLinkage(Ty); - - // Add the vtable pointer. - BuildVTablePointer(cast(Ty)); - - // And the name. - llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); - llvm::Constant *TypeNameField; - - // If we're supposed to demote the visibility, be sure to set a flag - // to use a string comparison for type_info comparisons. - CGCXXABI::RTTIUniquenessKind RTTIUniqueness = - CGM.getCXXABI().classifyRTTIUniqueness(Ty, Linkage); - if (RTTIUniqueness != CGCXXABI::RUK_Unique) { - // The flag is the sign bit, which on ARM64 is defined to be clear - // for global pointers. This is very ARM64-specific. - TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty); - llvm::Constant *flag = - llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63); - TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag); - TypeNameField = - llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy); - } else { - TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy); - } - Fields.push_back(TypeNameField); - - switch (Ty->getTypeClass()) { -#define TYPE(Class, Base) -#define ABSTRACT_TYPE(Class, Base) -#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: -#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: -#define DEPENDENT_TYPE(Class, Base) case Type::Class: -#include "clang/AST/TypeNodes.def" - llvm_unreachable("Non-canonical and dependent types shouldn't get here"); - - // GCC treats vector types as fundamental types. - case Type::Builtin: - case Type::Vector: - case Type::ExtVector: - case Type::Complex: - case Type::BlockPointer: - // Itanium C++ ABI 2.9.5p4: - // abi::__fundamental_type_info adds no data members to std::type_info. - break; - - case Type::LValueReference: - case Type::RValueReference: - llvm_unreachable("References shouldn't get here"); - - case Type::Auto: - llvm_unreachable("Undeduced auto type shouldn't get here"); - - case Type::ConstantArray: - case Type::IncompleteArray: - case Type::VariableArray: - // Itanium C++ ABI 2.9.5p5: - // abi::__array_type_info adds no data members to std::type_info. - break; - - case Type::FunctionNoProto: - case Type::FunctionProto: - // Itanium C++ ABI 2.9.5p5: - // abi::__function_type_info adds no data members to std::type_info. - break; - - case Type::Enum: - // Itanium C++ ABI 2.9.5p5: - // abi::__enum_type_info adds no data members to std::type_info. - break; - - case Type::Record: { - const CXXRecordDecl *RD = - cast(cast(Ty)->getDecl()); - if (!RD->hasDefinition() || !RD->getNumBases()) { - // We don't need to emit any fields. - break; - } - - if (CanUseSingleInheritance(RD)) - BuildSIClassTypeInfo(RD); - else - BuildVMIClassTypeInfo(RD); - - break; - } - - case Type::ObjCObject: - case Type::ObjCInterface: - BuildObjCObjectTypeInfo(cast(Ty)); - break; - - case Type::ObjCObjectPointer: - BuildPointerTypeInfo(cast(Ty)->getPointeeType()); - break; - - case Type::Pointer: - BuildPointerTypeInfo(cast(Ty)->getPointeeType()); - break; - - case Type::MemberPointer: - BuildPointerToMemberTypeInfo(cast(Ty)); - break; - - case Type::Atomic: - // No fields, at least for the moment. - break; - } - - llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); - - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Init->getType(), - /*Constant=*/true, Linkage, Init, Name); - - // If there's already an old global variable, replace it with the new one. - if (OldGV) { - GV->takeName(OldGV); - llvm::Constant *NewPtr = - llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); - OldGV->replaceAllUsesWith(NewPtr); - OldGV->eraseFromParent(); - } - - // The Itanium ABI specifies that type_info objects must be globally - // unique, with one exception: if the type is an incomplete class - // type or a (possibly indirect) pointer to one. That exception - // affects the general case of comparing type_info objects produced - // by the typeid operator, which is why the comparison operators on - // std::type_info generally use the type_info name pointers instead - // of the object addresses. However, the language's built-in uses - // of RTTI generally require class types to be complete, even when - // manipulating pointers to those class types. This allows the - // implementation of dynamic_cast to rely on address equality tests, - // which is much faster. - - // All of this is to say that it's important that both the type_info - // object and the type_info name be uniqued when weakly emitted. - - // Give the type_info object and name the formal visibility of the - // type itself. - llvm::GlobalValue::VisibilityTypes llvmVisibility; - if (llvm::GlobalValue::isLocalLinkage(Linkage)) - // If the linkage is local, only default visibility makes sense. - llvmVisibility = llvm::GlobalValue::DefaultVisibility; - else if (RTTIUniqueness == CGCXXABI::RUK_NonUniqueHidden) - llvmVisibility = llvm::GlobalValue::HiddenVisibility; - else - llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility()); - TypeName->setVisibility(llvmVisibility); - GV->setVisibility(llvmVisibility); - - return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); -} - -/// ComputeQualifierFlags - Compute the pointer type info flags from the -/// given qualifier. -static unsigned ComputeQualifierFlags(Qualifiers Quals) { - unsigned Flags = 0; - - if (Quals.hasConst()) - Flags |= ItaniumRTTIBuilder::PTI_Const; - if (Quals.hasVolatile()) - Flags |= ItaniumRTTIBuilder::PTI_Volatile; - if (Quals.hasRestrict()) - Flags |= ItaniumRTTIBuilder::PTI_Restrict; - - return Flags; -} - -/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info -/// for the given Objective-C object type. -void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) { - // Drop qualifiers. - const Type *T = OT->getBaseType().getTypePtr(); - assert(isa(T) || isa(T)); - - // The builtin types are abi::__class_type_infos and don't require - // extra fields. - if (isa(T)) return; - - ObjCInterfaceDecl *Class = cast(T)->getDecl(); - ObjCInterfaceDecl *Super = Class->getSuperClass(); - - // Root classes are also __class_type_info. - if (!Super) return; - - QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super); - - // Everything else is single inheritance. - 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 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 = - ItaniumRTTIBuilder(CGM).BuildTypeInfo(RD->bases_begin()->getType()); - Fields.push_back(BaseTypeInfo); -} - -namespace { - /// SeenBases - Contains virtual and non-virtual bases seen when traversing - /// a class hierarchy. - struct SeenBases { - llvm::SmallPtrSet NonVirtualBases; - llvm::SmallPtrSet VirtualBases; - }; -} - -/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in -/// abi::__vmi_class_type_info. -/// -static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, - SeenBases &Bases) { - - unsigned Flags = 0; - - const CXXRecordDecl *BaseDecl = - cast(Base->getType()->getAs()->getDecl()); - - if (Base->isVirtual()) { - // Mark the virtual base as seen. - if (!Bases.VirtualBases.insert(BaseDecl)) { - // If this virtual base has been seen before, then the class is diamond - // shaped. - Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped; - } else { - if (Bases.NonVirtualBases.count(BaseDecl)) - 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 |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; - } else { - if (Bases.VirtualBases.count(BaseDecl)) - Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; - } - } - - // Walk all bases. - for (const auto &I : BaseDecl->bases()) - Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); - - return Flags; -} - -static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) { - unsigned Flags = 0; - SeenBases Bases; - - // Walk all bases. - for (const auto &I : RD->bases()) - Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); - - return Flags; -} - -/// 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 ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { - llvm::Type *UnsignedIntLTy = - CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); - - // Itanium C++ ABI 2.9.5p6c: - // __flags is a word with flags describing details about the class - // structure, which may be referenced by using the __flags_masks - // enumeration. These flags refer to both direct and indirect bases. - unsigned Flags = ComputeVMIClassTypeInfoFlags(RD); - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); - - // Itanium C++ ABI 2.9.5p6c: - // __base_count is a word with the number of direct proper base class - // descriptions that follow. - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases())); - - if (!RD->getNumBases()) - return; - - llvm::Type *LongLTy = - CGM.getTypes().ConvertType(CGM.getContext().LongTy); - - // Now add the base class descriptions. - - // Itanium C++ ABI 2.9.5p6c: - // __base_info[] is an array of base class descriptions -- one for every - // direct proper base. Each description is of the type: - // - // struct abi::__base_class_type_info { - // public: - // const __class_type_info *__base_type; - // long __offset_flags; - // - // enum __offset_flags_masks { - // __virtual_mask = 0x1, - // __public_mask = 0x2, - // __offset_shift = 8 - // }; - // }; - for (const auto &Base : RD->bases()) { - // The __base_type member points to the RTTI for the base type. - Fields.push_back(ItaniumRTTIBuilder(CGM).BuildTypeInfo(Base.getType())); - - const CXXRecordDecl *BaseDecl = - cast(Base.getType()->getAs()->getDecl()); - - int64_t OffsetFlags = 0; - - // All but the lower 8 bits of __offset_flags are a signed offset. - // For a non-virtual base, this is the offset in the object of the base - // subobject. For a virtual base, this is the offset in the virtual table of - // the virtual base offset for the virtual base referenced (negative). - CharUnits Offset; - if (Base.isVirtual()) - Offset = - CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl); - else { - const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - Offset = Layout.getBaseClassOffset(BaseDecl); - }; - - OffsetFlags = uint64_t(Offset.getQuantity()) << 8; - - // The low-order byte of __offset_flags contains flags, as given by the - // masks from the enumeration __offset_flags_masks. - if (Base.isVirtual()) - OffsetFlags |= BCTI_Virtual; - if (Base.getAccessSpecifier() == AS_public) - OffsetFlags |= BCTI_Public; - - Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags)); - } -} - -/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, -/// used for pointer types. -void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { - Qualifiers Quals; - QualType UnqualifiedPointeeTy = - CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals); - - // Itanium C++ ABI 2.9.5p7: - // __flags is a flag word describing the cv-qualification and other - // attributes of the type pointed to - unsigned Flags = ComputeQualifierFlags(Quals); - - // Itanium C++ ABI 2.9.5p7: - // When the abi::__pbase_type_info is for a direct or indirect pointer to an - // incomplete class type, the incomplete target type flag is set. - if (ContainsIncompleteClassType(UnqualifiedPointeeTy)) - Flags |= PTI_Incomplete; - - llvm::Type *UnsignedIntLTy = - CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); - - // Itanium C++ ABI 2.9.5p7: - // __pointee is a pointer to the std::type_info derivation for the - // unqualified type being pointed to. - llvm::Constant *PointeeTypeInfo = - ItaniumRTTIBuilder(CGM).BuildTypeInfo(UnqualifiedPointeeTy); - Fields.push_back(PointeeTypeInfo); -} - -/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info -/// struct, used for member pointer types. -void -ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { - QualType PointeeTy = Ty->getPointeeType(); - - Qualifiers Quals; - QualType UnqualifiedPointeeTy = - CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals); - - // Itanium C++ ABI 2.9.5p7: - // __flags is a flag word describing the cv-qualification and other - // attributes of the type pointed to. - unsigned Flags = ComputeQualifierFlags(Quals); - - const RecordType *ClassType = cast(Ty->getClass()); - - // Itanium C++ ABI 2.9.5p7: - // When the abi::__pbase_type_info is for a direct or indirect pointer to an - // incomplete class type, the incomplete target type flag is set. - if (ContainsIncompleteClassType(UnqualifiedPointeeTy)) - Flags |= PTI_Incomplete; - - if (IsIncompleteClassType(ClassType)) - Flags |= PTI_ContainingClassIncomplete; - - llvm::Type *UnsignedIntLTy = - CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); - Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); - - // Itanium C++ ABI 2.9.5p7: - // __pointee is a pointer to the std::type_info derivation for the - // unqualified type being pointed to. - llvm::Constant *PointeeTypeInfo = - 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( - ItaniumRTTIBuilder(CGM).BuildTypeInfo(QualType(ClassType, 0))); -} - -llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, - bool ForEH) { - // Return a bogus pointer if RTTI is disabled, unless it's for EH. - // FIXME: should we even be calling this method if RTTI is disabled - // and it's not for EH? - if (!ForEH && !getLangOpts().RTTI) - return llvm::Constant::getNullValue(Int8PtrTy); - - if (ForEH && Ty->isObjCObjectPointerType() && - LangOpts.ObjCRuntime.isGNUFamily()) - return ObjCRuntime->GetEHType(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()); - ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, true); - ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, true); - ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true); -} - -void CodeGenModule::EmitFundamentalRTTIDescriptors() { - QualType FundamentalTypes[] = { Context.VoidTy, Context.NullPtrTy, - Context.BoolTy, Context.WCharTy, - Context.CharTy, Context.UnsignedCharTy, - Context.SignedCharTy, Context.ShortTy, - Context.UnsignedShortTy, Context.IntTy, - Context.UnsignedIntTy, Context.LongTy, - Context.UnsignedLongTy, Context.LongLongTy, - Context.UnsignedLongLongTy, - Context.HalfTy, Context.FloatTy, - Context.DoubleTy, Context.LongDoubleTy, - Context.Char16Ty, Context.Char32Ty }; - for (unsigned i = 0; i < llvm::array_lengthof(FundamentalTypes); ++i) - EmitFundamentalRTTIDescriptor(FundamentalTypes[i]); -} diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index 4b7d51b06..bb655c2 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -45,7 +45,6 @@ add_clang_library(clangCodeGen CGObjCRuntime.cpp CGOpenCLRuntime.cpp CGOpenMPRuntime.cpp - CGRTTI.cpp CGRecordLayoutBuilder.cpp CGStmt.cpp CGStmtOpenMP.cpp @@ -60,7 +59,6 @@ add_clang_library(clangCodeGen CodeGenTypes.cpp ItaniumCXXABI.cpp MicrosoftCXXABI.cpp - MicrosoftRTTI.cpp ModuleBuilder.cpp TargetInfo.cpp diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 2f840dd..ce99c2b 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3389,3 +3389,19 @@ llvm::Constant *CodeGenModule::EmitUuidofInitializer(StringRef Uuid, return llvm::ConstantStruct::getAnon(Fields); } + +llvm::Constant *CodeGenModule::GetAddrOfRTTIDescriptor(QualType Ty, + bool ForEH) { + // Return a bogus pointer if RTTI is disabled, unless it's for EH. + // FIXME: should we even be calling this method if RTTI is disabled + // and it's not for EH? + if (!ForEH && !getLangOpts().RTTI) + return llvm::Constant::getNullValue(Int8PtrTy); + + if (ForEH && Ty->isObjCObjectPointerType() && + LangOpts.ObjCRuntime.isGNUFamily()) + return ObjCRuntime->GetEHType(Ty); + + return getCXXABI().getAddrOfRTTIDescriptor(Ty); +} + diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index c0bfb4c..8ce4668 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -747,12 +747,6 @@ 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::Constant *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 *); @@ -973,9 +967,6 @@ 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); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index c33eb62..baf0927 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -109,6 +109,10 @@ public: llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF, llvm::Value *ptr, QualType type) override; + void EmitFundamentalRTTIDescriptor(QualType Type); + void EmitFundamentalRTTIDescriptors(); + llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; + bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; void EmitBadTypeidCall(CodeGenFunction &CGF) override; llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, @@ -238,6 +242,37 @@ public: QualType LValType) override; bool NeedsVTTParameter(GlobalDecl GD) override; + + /**************************** RTTI Uniqueness ******************************/ + +protected: + /// Returns true if the ABI requires RTTI type_info objects to be unique + /// across a program. + virtual bool shouldRTTIBeUnique() const { return true; } + +public: + /// What sort of unique-RTTI behavior should we use? + enum RTTIUniquenessKind { + /// We are guaranteeing, or need to guarantee, that the RTTI string + /// is unique. + RUK_Unique, + + /// We are not guaranteeing uniqueness for the RTTI string, so we + /// can demote to hidden visibility but must use string comparisons. + RUK_NonUniqueHidden, + + /// We are not guaranteeing uniqueness for the RTTI string, so we + /// have to use string comparisons, but we also have to emit it with + /// non-hidden visibility. + RUK_NonUniqueVisible + }; + + /// Return the required visibility status for the given type and linkage in + /// the current ABI. + RTTIUniquenessKind + classifyRTTIUniqueness(QualType CanTy, + llvm::GlobalValue::LinkageTypes Linkage) const; + friend class ItaniumRTTIBuilder; }; class ARMCXXABI : public ItaniumCXXABI { @@ -270,7 +305,7 @@ public: iOS64CXXABI(CodeGen::CodeGenModule &CGM) : ARMCXXABI(CGM) {} // ARM64 libraries are prepared for non-unique RTTI. - bool shouldRTTIBeUnique() override { return false; } + bool shouldRTTIBeUnique() const override { return false; } }; } @@ -1206,7 +1241,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, isa(DC) && cast(DC)->getIdentifier() && cast(DC)->getIdentifier()->isStr("__cxxabiv1") && DC->getParent()->isTranslationUnit()) - CGM.EmitFundamentalRTTIDescriptors(); + EmitFundamentalRTTIDescriptors(); } llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructor( @@ -1944,3 +1979,996 @@ bool ItaniumCXXABI::NeedsVTTParameter(GlobalDecl GD) { return false; } + +namespace { +class ItaniumRTTIBuilder { + CodeGenModule &CGM; // Per-module state. + llvm::LLVMContext &VMContext; + const ItaniumCXXABI &CXXABI; // Per-module state. + + /// Fields - The fields of the RTTI descriptor currently being built. + SmallVector Fields; + + /// GetAddrOfTypeName - Returns the mangled type name of the given type. + llvm::GlobalVariable * + GetAddrOfTypeName(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage); + + /// GetAddrOfExternalRTTIDescriptor - Returns the constant for the RTTI + /// descriptor of the given type. + llvm::Constant *GetAddrOfExternalRTTIDescriptor(QualType Ty); + + /// BuildVTablePointer - Build the vtable pointer for the given type. + void BuildVTablePointer(const Type *Ty); + + /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single + /// inheritance, according to the Itanium C++ ABI, 2.9.5p6b. + void BuildSIClassTypeInfo(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 BuildVMIClassTypeInfo(const CXXRecordDecl *RD); + + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used + /// for pointer types. + void BuildPointerTypeInfo(QualType PointeeTy); + + /// BuildObjCObjectTypeInfo - Build the appropriate kind of + /// type_info for an object type. + void BuildObjCObjectTypeInfo(const ObjCObjectType *Ty); + + /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info + /// struct, used for member pointer types. + void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty); + +public: + ItaniumRTTIBuilder(const ItaniumCXXABI &ABI) + : CGM(ABI.CGM), VMContext(CGM.getModule().getContext()), CXXABI(ABI) {} + + // Pointer type info flags. + enum { + /// PTI_Const - Type has const qualifier. + PTI_Const = 0x1, + + /// PTI_Volatile - Type has volatile qualifier. + PTI_Volatile = 0x2, + + /// PTI_Restrict - Type has restrict qualifier. + PTI_Restrict = 0x4, + + /// PTI_Incomplete - Type is incomplete. + PTI_Incomplete = 0x8, + + /// PTI_ContainingClassIncomplete - Containing class is incomplete. + /// (in pointer to member). + PTI_ContainingClassIncomplete = 0x10 + }; + + // VMI type info flags. + enum { + /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance. + VMI_NonDiamondRepeat = 0x1, + + /// VMI_DiamondShaped - Class is diamond shaped. + VMI_DiamondShaped = 0x2 + }; + + // Base class type info flags. + enum { + /// BCTI_Virtual - Base class is virtual. + BCTI_Virtual = 0x1, + + /// BCTI_Public - Base class is public. + BCTI_Public = 0x2 + }; + + /// BuildTypeInfo - Build the RTTI type info struct for the given type. + /// + /// \param Force - true to force the creation of this RTTI value + llvm::Constant *BuildTypeInfo(QualType Ty, bool Force = false); +}; +} + +llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName( + QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) { + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out); + Out.flush(); + StringRef Name = OutName.str(); + + // We know that the mangled name of the type starts at index 4 of the + // mangled name of the typename, so we can just index into it in order to + // get the mangled name of the type. + llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext, + Name.substr(4)); + + llvm::GlobalVariable *GV = + CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage); + + GV->setInitializer(Init); + + return GV; +} + +llvm::Constant * +ItaniumRTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { + // Mangle the RTTI name. + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); + Out.flush(); + StringRef Name = OutName.str(); + + // Look for an existing global. + llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name); + + if (!GV) { + // Create a new global variable. + GV = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8PtrTy, + /*Constant=*/true, + llvm::GlobalValue::ExternalLinkage, nullptr, + Name); + } + + return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); +} + +/// TypeInfoIsInStandardLibrary - Given a builtin type, returns whether the type +/// info for that type is defined in the standard library. +static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { + // Itanium C++ ABI 2.9.2: + // Basic type information (e.g. for "int", "bool", etc.) will be kept in + // the run-time support library. Specifically, the run-time support + // library should contain type_info objects for the types X, X* and + // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char, + // unsigned char, signed char, short, unsigned short, int, unsigned int, + // long, unsigned long, long long, unsigned long long, float, double, + // long double, char16_t, char32_t, and the IEEE 754r decimal and + // half-precision floating point types. + switch (Ty->getKind()) { + case BuiltinType::Void: + case BuiltinType::NullPtr: + case BuiltinType::Bool: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + case BuiltinType::Char_U: + case BuiltinType::Char_S: + case BuiltinType::UChar: + case BuiltinType::SChar: + case BuiltinType::Short: + case BuiltinType::UShort: + case BuiltinType::Int: + case BuiltinType::UInt: + case BuiltinType::Long: + case BuiltinType::ULong: + case BuiltinType::LongLong: + case BuiltinType::ULongLong: + case BuiltinType::Half: + case BuiltinType::Float: + case BuiltinType::Double: + case BuiltinType::LongDouble: + case BuiltinType::Char16: + case BuiltinType::Char32: + case BuiltinType::Int128: + case BuiltinType::UInt128: + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + case BuiltinType::OCLSampler: + case BuiltinType::OCLEvent: + return true; + + case BuiltinType::Dependent: +#define BUILTIN_TYPE(Id, SingletonId) +#define PLACEHOLDER_TYPE(Id, SingletonId) \ + case BuiltinType::Id: +#include "clang/AST/BuiltinTypes.def" + llvm_unreachable("asking for RRTI for a placeholder type!"); + + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + llvm_unreachable("FIXME: Objective-C types are unsupported!"); + } + + llvm_unreachable("Invalid BuiltinType Kind!"); +} + +static bool TypeInfoIsInStandardLibrary(const PointerType *PointerTy) { + QualType PointeeTy = PointerTy->getPointeeType(); + const BuiltinType *BuiltinTy = dyn_cast(PointeeTy); + if (!BuiltinTy) + return false; + + // Check the qualifiers. + Qualifiers Quals = PointeeTy.getQualifiers(); + Quals.removeConst(); + + if (!Quals.empty()) + return false; + + return TypeInfoIsInStandardLibrary(BuiltinTy); +} + +/// IsStandardLibraryRTTIDescriptor - Returns whether the type +/// information for the given type exists in the standard library. +static bool IsStandardLibraryRTTIDescriptor(QualType Ty) { + // Type info for builtin types is defined in the standard library. + if (const BuiltinType *BuiltinTy = dyn_cast(Ty)) + return TypeInfoIsInStandardLibrary(BuiltinTy); + + // Type info for some pointer types to builtin types is defined in the + // standard library. + if (const PointerType *PointerTy = dyn_cast(Ty)) + return TypeInfoIsInStandardLibrary(PointerTy); + + return false; +} + +/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for +/// the given type exists somewhere else, and that we should not emit the type +/// information in this translation unit. Assumes that it is not a +/// standard-library type. +static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, + QualType Ty) { + ASTContext &Context = CGM.getContext(); + + // If RTTI is disabled, assume it might be disabled in the + // translation unit that defines any potential key function, too. + if (!Context.getLangOpts().RTTI) return false; + + if (const RecordType *RecordTy = dyn_cast(Ty)) { + const CXXRecordDecl *RD = cast(RecordTy->getDecl()); + if (!RD->hasDefinition()) + return false; + + if (!RD->isDynamicClass()) + return false; + + // FIXME: this may need to be reconsidered if the key function + // changes. + return CGM.getVTables().isVTableExternal(RD); + } + + return false; +} + +/// IsIncompleteClassType - Returns whether the given record type is incomplete. +static bool IsIncompleteClassType(const RecordType *RecordTy) { + return !RecordTy->getDecl()->isCompleteDefinition(); +} + +/// ContainsIncompleteClassType - Returns whether the given type contains an +/// incomplete class type. This is true if +/// +/// * The given type is an incomplete class type. +/// * The given type is a pointer type whose pointee type contains an +/// incomplete class type. +/// * The given type is a member pointer type whose class is an incomplete +/// class type. +/// * The given type is a member pointer type whoise pointee type contains an +/// incomplete class type. +/// is an indirect or direct pointer to an incomplete class type. +static bool ContainsIncompleteClassType(QualType Ty) { + if (const RecordType *RecordTy = dyn_cast(Ty)) { + if (IsIncompleteClassType(RecordTy)) + return true; + } + + if (const PointerType *PointerTy = dyn_cast(Ty)) + return ContainsIncompleteClassType(PointerTy->getPointeeType()); + + if (const MemberPointerType *MemberPointerTy = + dyn_cast(Ty)) { + // Check if the class type is incomplete. + const RecordType *ClassType = cast(MemberPointerTy->getClass()); + if (IsIncompleteClassType(ClassType)) + return true; + + return ContainsIncompleteClassType(MemberPointerTy->getPointeeType()); + } + + return false; +} + +// CanUseSingleInheritance - Return whether the given record decl has a "single, +// public, non-virtual base at offset zero (i.e. the derived class is dynamic +// iff the base is)", according to Itanium C++ ABI, 2.95p6b. +static bool CanUseSingleInheritance(const CXXRecordDecl *RD) { + // Check the number of bases. + if (RD->getNumBases() != 1) + return false; + + // Get the base. + CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(); + + // Check that the base is not virtual. + if (Base->isVirtual()) + return false; + + // Check that the base is public. + if (Base->getAccessSpecifier() != AS_public) + return false; + + // Check that the class is dynamic iff the base is. + const CXXRecordDecl *BaseDecl = + cast(Base->getType()->getAs()->getDecl()); + if (!BaseDecl->isEmpty() && + BaseDecl->isDynamicClass() != RD->isDynamicClass()) + return false; + + return true; +} + +void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) { + // abi::__class_type_info. + static const char * const ClassTypeInfo = + "_ZTVN10__cxxabiv117__class_type_infoE"; + // abi::__si_class_type_info. + static const char * const SIClassTypeInfo = + "_ZTVN10__cxxabiv120__si_class_type_infoE"; + // abi::__vmi_class_type_info. + static const char * const VMIClassTypeInfo = + "_ZTVN10__cxxabiv121__vmi_class_type_infoE"; + + const char *VTableName = nullptr; + + switch (Ty->getTypeClass()) { +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("Non-canonical and dependent types shouldn't get here"); + + case Type::LValueReference: + case Type::RValueReference: + llvm_unreachable("References shouldn't get here"); + + case Type::Auto: + llvm_unreachable("Undeduced auto type shouldn't get here"); + + case Type::Builtin: + // GCC treats vector and complex types as fundamental types. + case Type::Vector: + case Type::ExtVector: + case Type::Complex: + case Type::Atomic: + // FIXME: GCC treats block pointers as fundamental types?! + case Type::BlockPointer: + // abi::__fundamental_type_info. + VTableName = "_ZTVN10__cxxabiv123__fundamental_type_infoE"; + break; + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + // abi::__array_type_info. + VTableName = "_ZTVN10__cxxabiv117__array_type_infoE"; + break; + + case Type::FunctionNoProto: + case Type::FunctionProto: + // abi::__function_type_info. + VTableName = "_ZTVN10__cxxabiv120__function_type_infoE"; + break; + + case Type::Enum: + // abi::__enum_type_info. + VTableName = "_ZTVN10__cxxabiv116__enum_type_infoE"; + break; + + case Type::Record: { + const CXXRecordDecl *RD = + cast(cast(Ty)->getDecl()); + + if (!RD->hasDefinition() || !RD->getNumBases()) { + VTableName = ClassTypeInfo; + } else if (CanUseSingleInheritance(RD)) { + VTableName = SIClassTypeInfo; + } else { + VTableName = VMIClassTypeInfo; + } + + break; + } + + case Type::ObjCObject: + // Ignore protocol qualifiers. + Ty = cast(Ty)->getBaseType().getTypePtr(); + + // Handle id and Class. + if (isa(Ty)) { + VTableName = ClassTypeInfo; + break; + } + + assert(isa(Ty)); + // Fall through. + + case Type::ObjCInterface: + if (cast(Ty)->getDecl()->getSuperClass()) { + VTableName = SIClassTypeInfo; + } else { + VTableName = ClassTypeInfo; + } + break; + + case Type::ObjCObjectPointer: + case Type::Pointer: + // abi::__pointer_type_info. + VTableName = "_ZTVN10__cxxabiv119__pointer_type_infoE"; + break; + + case Type::MemberPointer: + // abi::__pointer_to_member_type_info. + VTableName = "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE"; + break; + } + + llvm::Constant *VTable = + CGM.getModule().getOrInsertGlobal(VTableName, CGM.Int8PtrTy); + + llvm::Type *PtrDiffTy = + CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType()); + + // The vtable address point is 2. + llvm::Constant *Two = llvm::ConstantInt::get(PtrDiffTy, 2); + VTable = llvm::ConstantExpr::getInBoundsGetElementPtr(VTable, Two); + VTable = llvm::ConstantExpr::getBitCast(VTable, CGM.Int8PtrTy); + + Fields.push_back(VTable); +} + +/// \brief 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) { + // 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 + // incomplete class type must be prevented from resolving to the + // corresponding type_info structs for the complete class type, possibly + // by making them local static objects. Finally, a dummy class RTTI is + // generated for the incomplete type that will not resolve to the final + // complete class RTTI (because the latter need not exist), possibly by + // making it a local static object. + if (ContainsIncompleteClassType(Ty)) + return llvm::GlobalValue::InternalLinkage; + + switch (Ty->getLinkage()) { + case NoLinkage: + case InternalLinkage: + case UniqueExternalLinkage: + return llvm::GlobalValue::InternalLinkage; + + case VisibleNoLinkage: + case ExternalLinkage: + if (!CGM.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; + } + + if (const RecordType *Record = dyn_cast(Ty)) { + const CXXRecordDecl *RD = cast(Record->getDecl()); + if (RD->hasAttr()) + return llvm::GlobalValue::WeakODRLinkage; + if (RD->isDynamicClass()) + return CGM.getVTableLinkage(RD); + } + + return llvm::GlobalValue::LinkOnceODRLinkage; + } + + llvm_unreachable("Invalid linkage!"); +} + +llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { + // We want to operate on the canonical type. + Ty = CGM.getContext().getCanonicalType(Ty); + + // Check if we've already emitted an RTTI descriptor for this type. + SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); + Out.flush(); + StringRef Name = OutName.str(); + + llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); + if (OldGV && !OldGV->isDeclaration()) { + assert(!OldGV->hasAvailableExternallyLinkage() && + "available_externally typeinfos not yet implemented"); + + return llvm::ConstantExpr::getBitCast(OldGV, CGM.Int8PtrTy); + } + + // Check if there is already an external RTTI descriptor for this type. + bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty); + if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty))) + return GetAddrOfExternalRTTIDescriptor(Ty); + + // Emit the standard library with external linkage. + llvm::GlobalVariable::LinkageTypes Linkage; + if (IsStdLib) + Linkage = llvm::GlobalValue::ExternalLinkage; + else + Linkage = getTypeInfoLinkage(CGM, Ty); + + // Add the vtable pointer. + BuildVTablePointer(cast(Ty)); + + // And the name. + llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); + llvm::Constant *TypeNameField; + + // If we're supposed to demote the visibility, be sure to set a flag + // to use a string comparison for type_info comparisons. + ItaniumCXXABI::RTTIUniquenessKind RTTIUniqueness = + CXXABI.classifyRTTIUniqueness(Ty, Linkage); + if (RTTIUniqueness != ItaniumCXXABI::RUK_Unique) { + // The flag is the sign bit, which on ARM64 is defined to be clear + // for global pointers. This is very ARM64-specific. + TypeNameField = llvm::ConstantExpr::getPtrToInt(TypeName, CGM.Int64Ty); + llvm::Constant *flag = + llvm::ConstantInt::get(CGM.Int64Ty, ((uint64_t)1) << 63); + TypeNameField = llvm::ConstantExpr::getAdd(TypeNameField, flag); + TypeNameField = + llvm::ConstantExpr::getIntToPtr(TypeNameField, CGM.Int8PtrTy); + } else { + TypeNameField = llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy); + } + Fields.push_back(TypeNameField); + + switch (Ty->getTypeClass()) { +#define TYPE(Class, Base) +#define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_TYPE(Class, Base) case Type::Class: +#define DEPENDENT_TYPE(Class, Base) case Type::Class: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("Non-canonical and dependent types shouldn't get here"); + + // GCC treats vector types as fundamental types. + case Type::Builtin: + case Type::Vector: + case Type::ExtVector: + case Type::Complex: + case Type::BlockPointer: + // Itanium C++ ABI 2.9.5p4: + // abi::__fundamental_type_info adds no data members to std::type_info. + break; + + case Type::LValueReference: + case Type::RValueReference: + llvm_unreachable("References shouldn't get here"); + + case Type::Auto: + llvm_unreachable("Undeduced auto type shouldn't get here"); + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: + // Itanium C++ ABI 2.9.5p5: + // abi::__array_type_info adds no data members to std::type_info. + break; + + case Type::FunctionNoProto: + case Type::FunctionProto: + // Itanium C++ ABI 2.9.5p5: + // abi::__function_type_info adds no data members to std::type_info. + break; + + case Type::Enum: + // Itanium C++ ABI 2.9.5p5: + // abi::__enum_type_info adds no data members to std::type_info. + break; + + case Type::Record: { + const CXXRecordDecl *RD = + cast(cast(Ty)->getDecl()); + if (!RD->hasDefinition() || !RD->getNumBases()) { + // We don't need to emit any fields. + break; + } + + if (CanUseSingleInheritance(RD)) + BuildSIClassTypeInfo(RD); + else + BuildVMIClassTypeInfo(RD); + + break; + } + + case Type::ObjCObject: + case Type::ObjCInterface: + BuildObjCObjectTypeInfo(cast(Ty)); + break; + + case Type::ObjCObjectPointer: + BuildPointerTypeInfo(cast(Ty)->getPointeeType()); + break; + + case Type::Pointer: + BuildPointerTypeInfo(cast(Ty)->getPointeeType()); + break; + + case Type::MemberPointer: + BuildPointerToMemberTypeInfo(cast(Ty)); + break; + + case Type::Atomic: + // No fields, at least for the moment. + break; + } + + llvm::Constant *Init = llvm::ConstantStruct::getAnon(Fields); + + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(CGM.getModule(), Init->getType(), + /*Constant=*/true, Linkage, Init, Name); + + // If there's already an old global variable, replace it with the new one. + if (OldGV) { + GV->takeName(OldGV); + llvm::Constant *NewPtr = + llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); + OldGV->replaceAllUsesWith(NewPtr); + OldGV->eraseFromParent(); + } + + // The Itanium ABI specifies that type_info objects must be globally + // unique, with one exception: if the type is an incomplete class + // type or a (possibly indirect) pointer to one. That exception + // affects the general case of comparing type_info objects produced + // by the typeid operator, which is why the comparison operators on + // std::type_info generally use the type_info name pointers instead + // of the object addresses. However, the language's built-in uses + // of RTTI generally require class types to be complete, even when + // manipulating pointers to those class types. This allows the + // implementation of dynamic_cast to rely on address equality tests, + // which is much faster. + + // All of this is to say that it's important that both the type_info + // object and the type_info name be uniqued when weakly emitted. + + // Give the type_info object and name the formal visibility of the + // type itself. + llvm::GlobalValue::VisibilityTypes llvmVisibility; + if (llvm::GlobalValue::isLocalLinkage(Linkage)) + // If the linkage is local, only default visibility makes sense. + llvmVisibility = llvm::GlobalValue::DefaultVisibility; + else if (RTTIUniqueness == ItaniumCXXABI::RUK_NonUniqueHidden) + llvmVisibility = llvm::GlobalValue::HiddenVisibility; + else + llvmVisibility = CodeGenModule::GetLLVMVisibility(Ty->getVisibility()); + TypeName->setVisibility(llvmVisibility); + GV->setVisibility(llvmVisibility); + + return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); +} + +/// ComputeQualifierFlags - Compute the pointer type info flags from the +/// given qualifier. +static unsigned ComputeQualifierFlags(Qualifiers Quals) { + unsigned Flags = 0; + + if (Quals.hasConst()) + Flags |= ItaniumRTTIBuilder::PTI_Const; + if (Quals.hasVolatile()) + Flags |= ItaniumRTTIBuilder::PTI_Volatile; + if (Quals.hasRestrict()) + Flags |= ItaniumRTTIBuilder::PTI_Restrict; + + return Flags; +} + +/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info +/// for the given Objective-C object type. +void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) { + // Drop qualifiers. + const Type *T = OT->getBaseType().getTypePtr(); + assert(isa(T) || isa(T)); + + // The builtin types are abi::__class_type_infos and don't require + // extra fields. + if (isa(T)) return; + + ObjCInterfaceDecl *Class = cast(T)->getDecl(); + ObjCInterfaceDecl *Super = Class->getSuperClass(); + + // Root classes are also __class_type_info. + if (!Super) return; + + QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super); + + // Everything else is single inheritance. + llvm::Constant *BaseTypeInfo = + ItaniumRTTIBuilder(CXXABI).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 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 = + ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType()); + Fields.push_back(BaseTypeInfo); +} + +namespace { + /// SeenBases - Contains virtual and non-virtual bases seen when traversing + /// a class hierarchy. + struct SeenBases { + llvm::SmallPtrSet NonVirtualBases; + llvm::SmallPtrSet VirtualBases; + }; +} + +/// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in +/// abi::__vmi_class_type_info. +/// +static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base, + SeenBases &Bases) { + + unsigned Flags = 0; + + const CXXRecordDecl *BaseDecl = + cast(Base->getType()->getAs()->getDecl()); + + if (Base->isVirtual()) { + // Mark the virtual base as seen. + if (!Bases.VirtualBases.insert(BaseDecl)) { + // If this virtual base has been seen before, then the class is diamond + // shaped. + Flags |= ItaniumRTTIBuilder::VMI_DiamondShaped; + } else { + if (Bases.NonVirtualBases.count(BaseDecl)) + 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 |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; + } else { + if (Bases.VirtualBases.count(BaseDecl)) + Flags |= ItaniumRTTIBuilder::VMI_NonDiamondRepeat; + } + } + + // Walk all bases. + for (const auto &I : BaseDecl->bases()) + Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); + + return Flags; +} + +static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) { + unsigned Flags = 0; + SeenBases Bases; + + // Walk all bases. + for (const auto &I : RD->bases()) + Flags |= ComputeVMIClassTypeInfoFlags(&I, Bases); + + return Flags; +} + +/// 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 ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { + llvm::Type *UnsignedIntLTy = + CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); + + // Itanium C++ ABI 2.9.5p6c: + // __flags is a word with flags describing details about the class + // structure, which may be referenced by using the __flags_masks + // enumeration. These flags refer to both direct and indirect bases. + unsigned Flags = ComputeVMIClassTypeInfoFlags(RD); + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); + + // Itanium C++ ABI 2.9.5p6c: + // __base_count is a word with the number of direct proper base class + // descriptions that follow. + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, RD->getNumBases())); + + if (!RD->getNumBases()) + return; + + llvm::Type *LongLTy = + CGM.getTypes().ConvertType(CGM.getContext().LongTy); + + // Now add the base class descriptions. + + // Itanium C++ ABI 2.9.5p6c: + // __base_info[] is an array of base class descriptions -- one for every + // direct proper base. Each description is of the type: + // + // struct abi::__base_class_type_info { + // public: + // const __class_type_info *__base_type; + // long __offset_flags; + // + // enum __offset_flags_masks { + // __virtual_mask = 0x1, + // __public_mask = 0x2, + // __offset_shift = 8 + // }; + // }; + for (const auto &Base : RD->bases()) { + // The __base_type member points to the RTTI for the base type. + Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType())); + + const CXXRecordDecl *BaseDecl = + cast(Base.getType()->getAs()->getDecl()); + + int64_t OffsetFlags = 0; + + // All but the lower 8 bits of __offset_flags are a signed offset. + // For a non-virtual base, this is the offset in the object of the base + // subobject. For a virtual base, this is the offset in the virtual table of + // the virtual base offset for the virtual base referenced (negative). + CharUnits Offset; + if (Base.isVirtual()) + Offset = + CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl); + else { + const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); + Offset = Layout.getBaseClassOffset(BaseDecl); + }; + + OffsetFlags = uint64_t(Offset.getQuantity()) << 8; + + // The low-order byte of __offset_flags contains flags, as given by the + // masks from the enumeration __offset_flags_masks. + if (Base.isVirtual()) + OffsetFlags |= BCTI_Virtual; + if (Base.getAccessSpecifier() == AS_public) + OffsetFlags |= BCTI_Public; + + Fields.push_back(llvm::ConstantInt::get(LongLTy, OffsetFlags)); + } +} + +/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, +/// used for pointer types. +void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { + Qualifiers Quals; + QualType UnqualifiedPointeeTy = + CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals); + + // Itanium C++ ABI 2.9.5p7: + // __flags is a flag word describing the cv-qualification and other + // attributes of the type pointed to + unsigned Flags = ComputeQualifierFlags(Quals); + + // Itanium C++ ABI 2.9.5p7: + // When the abi::__pbase_type_info is for a direct or indirect pointer to an + // incomplete class type, the incomplete target type flag is set. + if (ContainsIncompleteClassType(UnqualifiedPointeeTy)) + Flags |= PTI_Incomplete; + + llvm::Type *UnsignedIntLTy = + CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); + + // Itanium C++ ABI 2.9.5p7: + // __pointee is a pointer to the std::type_info derivation for the + // unqualified type being pointed to. + llvm::Constant *PointeeTypeInfo = + ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy); + Fields.push_back(PointeeTypeInfo); +} + +/// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info +/// struct, used for member pointer types. +void +ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { + QualType PointeeTy = Ty->getPointeeType(); + + Qualifiers Quals; + QualType UnqualifiedPointeeTy = + CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals); + + // Itanium C++ ABI 2.9.5p7: + // __flags is a flag word describing the cv-qualification and other + // attributes of the type pointed to. + unsigned Flags = ComputeQualifierFlags(Quals); + + const RecordType *ClassType = cast(Ty->getClass()); + + // Itanium C++ ABI 2.9.5p7: + // When the abi::__pbase_type_info is for a direct or indirect pointer to an + // incomplete class type, the incomplete target type flag is set. + if (ContainsIncompleteClassType(UnqualifiedPointeeTy)) + Flags |= PTI_Incomplete; + + if (IsIncompleteClassType(ClassType)) + Flags |= PTI_ContainingClassIncomplete; + + llvm::Type *UnsignedIntLTy = + CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); + Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags)); + + // Itanium C++ ABI 2.9.5p7: + // __pointee is a pointer to the std::type_info derivation for the + // unqualified type being pointed to. + llvm::Constant *PointeeTypeInfo = + ItaniumRTTIBuilder(CXXABI).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( + ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0))); +} + +llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) { + return ItaniumRTTIBuilder(*this).BuildTypeInfo(Ty); +} + +void ItaniumCXXABI::EmitFundamentalRTTIDescriptor(QualType Type) { + QualType PointerType = getContext().getPointerType(Type); + QualType PointerTypeConst = getContext().getPointerType(Type.withConst()); + ItaniumRTTIBuilder(*this).BuildTypeInfo(Type, true); + ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerType, true); + ItaniumRTTIBuilder(*this).BuildTypeInfo(PointerTypeConst, true); +} + +void ItaniumCXXABI::EmitFundamentalRTTIDescriptors() { + QualType FundamentalTypes[] = { + getContext().VoidTy, getContext().NullPtrTy, + getContext().BoolTy, getContext().WCharTy, + getContext().CharTy, getContext().UnsignedCharTy, + getContext().SignedCharTy, getContext().ShortTy, + getContext().UnsignedShortTy, getContext().IntTy, + getContext().UnsignedIntTy, getContext().LongTy, + getContext().UnsignedLongTy, getContext().LongLongTy, + getContext().UnsignedLongLongTy, getContext().HalfTy, + getContext().FloatTy, getContext().DoubleTy, + getContext().LongDoubleTy, getContext().Char16Ty, + getContext().Char32Ty, + }; + for (const QualType &FundamentalType : FundamentalTypes) + EmitFundamentalRTTIDescriptor(FundamentalType); +} + +/// What sort of uniqueness rules should we use for the RTTI for the +/// given type? +ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness( + QualType CanTy, llvm::GlobalValue::LinkageTypes Linkage) const { + if (shouldRTTIBeUnique()) + return RUK_Unique; + + // It's only necessary for linkonce_odr or weak_odr linkage. + if (Linkage != llvm::GlobalValue::LinkOnceODRLinkage && + Linkage != llvm::GlobalValue::WeakODRLinkage) + return RUK_Unique; + + // It's only necessary with default visibility. + if (CanTy->getVisibility() != DefaultVisibility) + return RUK_Unique; + + // If we're not required to publish this symbol, hide it. + if (Linkage == llvm::GlobalValue::LinkOnceODRLinkage) + return RUK_NonUniqueHidden; + + // If we're required to publish this symbol, as we might be under an + // explicit instantiation, leave it with default visibility but + // enable string-comparisons. + assert(Linkage == llvm::GlobalValue::WeakODRLinkage); + return RUK_NonUniqueVisible; +} diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index c586e03..0b82208 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -57,6 +57,11 @@ public: llvm::Value *ptr, QualType type) override; + llvm::GlobalVariable *getMSCompleteObjectLocator(const CXXRecordDecl *RD, + const VPtrInfo *Info); + + llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; + bool shouldTypeidBeNullChecked(bool IsDeref, QualType SrcRecordTy) override; void EmitBadTypeidCall(CodeGenFunction &CGF) override; llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy, @@ -1059,7 +1064,7 @@ void MicrosoftCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, if (VTable->hasInitializer()) continue; - llvm::Constant *RTTI = CGM.getMSCompleteObjectLocator(RD, Info); + llvm::Constant *RTTI = getMSCompleteObjectLocator(RD, Info); const VTableLayout &VTLayout = VFTContext.getVFTableLayout(RD, Info->FullOffsetInMDC); @@ -2364,3 +2369,509 @@ llvm::Value *MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer( CGCXXABI *clang::CodeGen::CreateMicrosoftCXXABI(CodeGenModule &CGM) { return new MicrosoftCXXABI(CGM); } + +// 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. + +static bool isImageRelative(CodeGenModule &CGM) { + return CGM.getTarget().getPointerWidth(/*AddressSpace=*/0) == 64; +} + +static llvm::Type *getImageRelativeType(CodeGenModule &CGM, + llvm::Type *PtrType) { + if (!isImageRelative(CGM)) + return PtrType; + return CGM.IntTy; +} + +static llvm::GlobalVariable *getImageBase(CodeGenModule &CGM) { + StringRef Name = "__ImageBase"; + if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name)) + return GV; + + return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, + /*isConstant=*/true, + llvm::GlobalValue::ExternalLinkage, + /*Initializer=*/nullptr, Name); +} + +static llvm::Constant *getImageRelativeConstant(CodeGenModule &CGM, + llvm::Constant *PtrVal) { + if (!isImageRelative(CGM)) + return PtrVal; + + llvm::Constant *ImageBaseAsInt = + llvm::ConstantExpr::getPtrToInt(getImageBase(CGM), CGM.IntPtrTy); + llvm::Constant *PtrValAsInt = + llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy); + llvm::Constant *Diff = + llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt, + /*HasNUW=*/true, /*HasNSW=*/true); + return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy); +} + +// 5 routines for constructing the llvm types for MS RTTI structs. +static 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[] = { + getImageRelativeType(CGM, CGM.Int8PtrTy), + CGM.IntTy, + CGM.IntTy, + CGM.IntTy, + CGM.IntTy, + CGM.IntTy, + getImageRelativeType( + CGM, 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, + getImageRelativeType( + CGM, + 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::StructType *Type = llvm::StructType::create(CGM.getLLVMContext(), Name); + llvm::Type *FieldTypes[] = { + CGM.IntTy, + CGM.IntTy, + CGM.IntTy, + getImageRelativeType(CGM, CGM.Int8PtrTy), + getImageRelativeType( + CGM, getClassHierarchyDescriptorType(CGM)->getPointerTo()), + getImageRelativeType(CGM, Type), + }; + llvm::ArrayRef FieldTypesRef( + std::begin(FieldTypes), + isImageRelative(CGM) ? std::end(FieldTypes) : std::end(FieldTypes) - 1); + Type->setBody(FieldTypesRef); + return Type; +} + +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=*/nullptr, 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 = nullptr; + 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; +} + +static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) { + switch (Ty->getLinkage()) { + case NoLinkage: + case InternalLinkage: + case UniqueExternalLinkage: + return llvm::GlobalValue::InternalLinkage; + + case VisibleNoLinkage: + case ExternalLinkage: + return llvm::GlobalValue::LinkOnceODRLinkage; + } + llvm_unreachable("Invalid linkage!"); +} + +/// \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(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))), + Mangler( + cast(CGM.getCXXABI().getMangleContext())) {} + + llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes); + llvm::GlobalVariable * + getBaseClassArray(SmallVectorImpl &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 &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 &Classes) { + llvm::SmallPtrSet VirtualBases; + llvm::SmallPtrSet UniqueBases; + llvm::SmallPtrSet 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 initialize the CHD Fields. + SmallVector Classes; + serializeClassHierarchy(Classes, RD); + Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr); + 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=*/nullptr, + 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()), + getImageRelativeConstant(CGM, + llvm::ConstantExpr::getInBoundsGetElementPtr( + getBaseClassArray(Classes), + llvm::ArrayRef(GEPIndices))), + }; + CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); + return CHD; +} + +llvm::GlobalVariable * +MSRTTIBuilder::getBaseClassArray(SmallVectorImpl &Classes) { + SmallString<256> MangledName; + { + llvm::raw_svector_ostream Out(MangledName); + Mangler.mangleCXXRTTIBaseClassArray(RD, Out); + } + + // Forward-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 = getImageRelativeType( + CGM, getBaseClassDescriptorType(CGM)->getPointerTo()); + auto ArrayType = llvm::ArrayType::get(PtrType, Classes.size() + 1); + auto BCA = new llvm::GlobalVariable(Module, ArrayType, + /*Constant=*/true, Linkage, /*Initializer=*/nullptr, MangledName.c_str()); + + // Initialize the BaseClassArray. + SmallVector BaseClassArrayData; + for (MSRTTIClass &Class : Classes) + BaseClassArrayData.push_back( + getImageRelativeConstant(CGM, getBaseClassDescriptor(Class))); + BaseClassArrayData.push_back(llvm::Constant::getNullValue(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=*/nullptr, + MangledName.c_str()); + + // Initialize the BaseClassDescriptor. + llvm::Constant *Fields[] = { + getImageRelativeConstant( + CGM, CGM.GetAddrOfRTTIDescriptor(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), + getImageRelativeConstant( + CGM, 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=*/nullptr, MangledName.c_str()); + + // Initialize the CompleteObjectLocator. + llvm::Constant *Fields[] = { + llvm::ConstantInt::get(CGM.IntTy, isImageRelative(CGM)), + llvm::ConstantInt::get(CGM.IntTy, OffsetToTop), + llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset), + getImageRelativeConstant( + CGM, CGM.GetAddrOfRTTIDescriptor(Context.getTypeDeclType(RD))), + getImageRelativeConstant(CGM, getClassHierarchyDescriptor()), + getImageRelativeConstant(CGM, COL), + }; + llvm::ArrayRef FieldsRef(Fields); + if (!isImageRelative(CGM)) + FieldsRef = FieldsRef.slice(0, FieldsRef.size() - 1); + COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef)); + 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 *MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type) { + auto &Mangler(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 (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) + return llvm::ConstantExpr::getBitCast(GV, CGM.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(CGM), // VFPtr + llvm::ConstantPointerNull::get(CGM.Int8PtrTy), // Runtime data + llvm::ConstantDataArray::getString(CGM.getLLVMContext(), TypeInfoString)}; + llvm::StructType *TypeDescriptorType = + getTypeDescriptorType(CGM, TypeInfoString); + return llvm::ConstantExpr::getBitCast( + new llvm::GlobalVariable( + CGM.getModule(), TypeDescriptorType, /*Constant=*/false, + getLinkageForRTTI(Type), + llvm::ConstantStruct::get(TypeDescriptorType, Fields), + MangledName.c_str()), + CGM.Int8PtrTy); +} + +/// \brief Gets or a creates a Microsoft CompleteObjectLocator. +llvm::GlobalVariable * +MicrosoftCXXABI::getMSCompleteObjectLocator(const CXXRecordDecl *RD, + const VPtrInfo *Info) { + return MSRTTIBuilder(CGM, RD).getCompleteObjectLocator(Info); +} diff --git a/clang/lib/CodeGen/MicrosoftRTTI.cpp b/clang/lib/CodeGen/MicrosoftRTTI.cpp deleted file mode 100644 index f539bfb..0000000 --- a/clang/lib/CodeGen/MicrosoftRTTI.cpp +++ /dev/null @@ -1,529 +0,0 @@ -//===--- 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. - -static bool isImageRelative(CodeGenModule &CGM) { - return CGM.getTarget().getPointerWidth(/*AddressSpace=*/0) == 64; -} - -static llvm::Type *getImageRelativeType(CodeGenModule &CGM, - llvm::Type *PtrType) { - if (!isImageRelative(CGM)) - return PtrType; - return CGM.IntTy; -} - -static llvm::GlobalVariable *getImageBase(CodeGenModule &CGM) { - StringRef Name = "__ImageBase"; - if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(Name)) - return GV; - - return new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, - /*isConstant=*/true, - llvm::GlobalValue::ExternalLinkage, - /*Initializer=*/nullptr, Name); -} - -static llvm::Constant *getImageRelativeConstant(CodeGenModule &CGM, - llvm::Constant *PtrVal) { - if (!isImageRelative(CGM)) - return PtrVal; - - llvm::Constant *ImageBaseAsInt = - llvm::ConstantExpr::getPtrToInt(getImageBase(CGM), CGM.IntPtrTy); - llvm::Constant *PtrValAsInt = - llvm::ConstantExpr::getPtrToInt(PtrVal, CGM.IntPtrTy); - llvm::Constant *Diff = - llvm::ConstantExpr::getSub(PtrValAsInt, ImageBaseAsInt, - /*HasNUW=*/true, /*HasNSW=*/true); - return llvm::ConstantExpr::getTrunc(Diff, CGM.IntTy); -} - -// 5 routines for constructing the llvm types for MS RTTI structs. -static 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[] = { - getImageRelativeType(CGM, CGM.Int8PtrTy), - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - getImageRelativeType( - CGM, 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, - getImageRelativeType( - CGM, - 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::StructType *Type = llvm::StructType::create(CGM.getLLVMContext(), Name); - llvm::Type *FieldTypes[] = { - CGM.IntTy, - CGM.IntTy, - CGM.IntTy, - getImageRelativeType(CGM, CGM.Int8PtrTy), - getImageRelativeType( - CGM, getClassHierarchyDescriptorType(CGM)->getPointerTo()), - getImageRelativeType(CGM, Type), - }; - ArrayRef FieldTypesRef( - std::begin(FieldTypes), - isImageRelative(CGM) ? std::end(FieldTypes) : std::end(FieldTypes) - 1); - Type->setBody(FieldTypesRef); - return Type; -} - -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=*/nullptr, 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 = nullptr; - 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; -} - -static llvm::GlobalValue::LinkageTypes getLinkageForRTTI(QualType Ty) { - switch (Ty->getLinkage()) { - case NoLinkage: - case InternalLinkage: - case UniqueExternalLinkage: - return llvm::GlobalValue::InternalLinkage; - - case VisibleNoLinkage: - case ExternalLinkage: - return llvm::GlobalValue::LinkOnceODRLinkage; - } - llvm_unreachable("Invalid linkage!"); -} - -/// \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(getLinkageForRTTI(CGM.getContext().getTagDeclType(RD))), - Mangler( - cast(CGM.getCXXABI().getMangleContext())) {} - - llvm::GlobalVariable *getBaseClassDescriptor(const MSRTTIClass &Classes); - llvm::GlobalVariable * - getBaseClassArray(SmallVectorImpl &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 &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 &Classes) { - llvm::SmallPtrSet VirtualBases; - llvm::SmallPtrSet UniqueBases; - llvm::SmallPtrSet 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 initialize the CHD Fields. - SmallVector Classes; - serializeClassHierarchy(Classes, RD); - Classes.front().initialize(/*Parent=*/nullptr, /*Specifier=*/nullptr); - 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=*/nullptr, - 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()), - getImageRelativeConstant(CGM, - llvm::ConstantExpr::getInBoundsGetElementPtr( - getBaseClassArray(Classes), - ArrayRef(GEPIndices))), - }; - CHD->setInitializer(llvm::ConstantStruct::get(Type, Fields)); - return CHD; -} - -llvm::GlobalVariable * -MSRTTIBuilder::getBaseClassArray(SmallVectorImpl &Classes) { - SmallString<256> MangledName; - { - llvm::raw_svector_ostream Out(MangledName); - Mangler.mangleCXXRTTIBaseClassArray(RD, Out); - } - - // Forward-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 = getImageRelativeType( - CGM, getBaseClassDescriptorType(CGM)->getPointerTo()); - auto ArrayType = llvm::ArrayType::get(PtrType, Classes.size() + 1); - auto BCA = new llvm::GlobalVariable(Module, ArrayType, - /*Constant=*/true, Linkage, /*Initializer=*/nullptr, MangledName.c_str()); - - // Initialize the BaseClassArray. - SmallVector BaseClassArrayData; - for (MSRTTIClass &Class : Classes) - BaseClassArrayData.push_back( - getImageRelativeConstant(CGM, getBaseClassDescriptor(Class))); - BaseClassArrayData.push_back(llvm::Constant::getNullValue(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=*/nullptr, - MangledName.c_str()); - - // Initialize the BaseClassDescriptor. - llvm::Constant *Fields[] = { - getImageRelativeConstant( - CGM, 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), - getImageRelativeConstant( - CGM, 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=*/nullptr, MangledName.c_str()); - - // Initialize the CompleteObjectLocator. - llvm::Constant *Fields[] = { - llvm::ConstantInt::get(CGM.IntTy, isImageRelative(CGM)), - llvm::ConstantInt::get(CGM.IntTy, OffsetToTop), - llvm::ConstantInt::get(CGM.IntTy, VFPtrOffset), - getImageRelativeConstant( - CGM, CGM.getMSTypeDescriptor(Context.getTypeDeclType(RD))), - getImageRelativeConstant(CGM, getClassHierarchyDescriptor()), - getImageRelativeConstant(CGM, COL), - }; - ArrayRef FieldsRef(Fields); - if (!isImageRelative(CGM)) - FieldsRef = FieldsRef.slice(0, FieldsRef.size() - 1); - COL->setInitializer(llvm::ConstantStruct::get(Type, FieldsRef)); - 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(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, - getLinkageForRTTI(Type), - llvm::ConstantStruct::get(TypeDescriptorType, Fields), - MangledName.c_str()), - Int8PtrTy); -} - -llvm::Constant * -CodeGenModule::getMSCompleteObjectLocator(const CXXRecordDecl *RD, - const VPtrInfo *Info) { - if (!getLangOpts().RTTIData) - return llvm::Constant::getNullValue(Int8PtrTy); - return MSRTTIBuilder(*this, RD).getCompleteObjectLocator(Info); -} -- 2.7.4