diff options
Diffstat (limited to 'lib/CodeGen/CGRTTI.cpp')
-rw-r--r-- | lib/CodeGen/CGRTTI.cpp | 276 |
1 files changed, 164 insertions, 112 deletions
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index 60df613f65e8..7ec0ee4b5cab 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -30,6 +30,10 @@ class RTTIBuilder { /// Fields - The fields of the RTTI descriptor currently being built. llvm::SmallVector<llvm::Constant *, 16> 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); @@ -59,64 +63,10 @@ class RTTIBuilder { void BuildPointerToMemberTypeInfo(const MemberPointerType *Ty); public: - RTTIBuilder(CodeGenModule &cgm) - : CGM(cgm), VMContext(cgm.getModule().getContext()), - Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { } - - llvm::Constant *BuildName(QualType Ty, bool Hidden, - llvm::GlobalVariable::LinkageTypes Linkage) { - llvm::SmallString<256> OutName; - CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, OutName); - llvm::StringRef Name = OutName.str(); - - llvm::GlobalVariable *OGV = CGM.getModule().getNamedGlobal(Name); - if (OGV && !OGV->isDeclaration()) - return llvm::ConstantExpr::getBitCast(OGV, Int8PtrTy); - - llvm::Constant *C = llvm::ConstantArray::get(VMContext, Name.substr(4)); - - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), C->getType(), true, Linkage, - C, Name); - if (OGV) { - GV->takeName(OGV); - llvm::Constant *NewPtr = llvm::ConstantExpr::getBitCast(GV, - OGV->getType()); - OGV->replaceAllUsesWith(NewPtr); - OGV->eraseFromParent(); - } - if (Hidden) - GV->setVisibility(llvm::GlobalVariable::HiddenVisibility); - return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); - } + RTTIBuilder(CodeGenModule &CGM) : CGM(CGM), + VMContext(CGM.getModule().getContext()), + Int8PtrTy(llvm::Type::getInt8PtrTy(VMContext)) { } - // FIXME: unify with DecideExtern - bool DecideHidden(QualType Ty) { - // For this type, see if all components are never hidden. - if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) - return (DecideHidden(MPT->getPointeeType()) - && DecideHidden(QualType(MPT->getClass(), 0))); - if (const PointerType *PT = Ty->getAs<PointerType>()) - return DecideHidden(PT->getPointeeType()); - if (const FunctionType *FT = Ty->getAs<FunctionType>()) { - if (DecideHidden(FT->getResultType()) == false) - return false; - if (const FunctionProtoType *FPT = Ty->getAs<FunctionProtoType>()) { - for (unsigned i = 0; i <FPT->getNumArgs(); ++i) - if (DecideHidden(FPT->getArgType(i)) == false) - return false; - for (unsigned i = 0; i <FPT->getNumExceptions(); ++i) - if (DecideHidden(FPT->getExceptionType(i)) == false) - return false; - return true; - } - } - if (const RecordType *RT = Ty->getAs<RecordType>()) - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) - return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden; - return false; - } - // Pointer type info flags. enum { /// PTI_Const - Type has const qualifier. @@ -162,10 +112,34 @@ public: }; } +llvm::GlobalVariable * +RTTIBuilder::GetAddrOfTypeName(QualType Ty, + llvm::GlobalVariable::LinkageTypes Linkage) { + llvm::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out); + Out.flush(); + llvm::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::ConstantArray::get(VMContext, Name.substr(4)); + + llvm::GlobalVariable *GV = + CGM.CreateOrReplaceCXXRuntimeVariable(Name, Init->getType(), Linkage); + + GV->setInitializer(Init); + + return GV; +} + llvm::Constant *RTTIBuilder::GetAddrOfExternalRTTIDescriptor(QualType Ty) { // Mangle the RTTI name. llvm::SmallString<256> OutName; - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName); + llvm::raw_svector_ostream Out(OutName); + CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); + Out.flush(); llvm::StringRef Name = OutName.str(); // Look for an existing global. @@ -187,15 +161,17 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { // 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, 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. + // 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: + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: case BuiltinType::Char_U: case BuiltinType::Char_S: case BuiltinType::UChar: @@ -219,12 +195,8 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) { case BuiltinType::Overload: case BuiltinType::Dependent: - case BuiltinType::UndeducedAuto: assert(false && "Should not see this type here!"); - case BuiltinType::NullPtr: - assert(false && "FIXME: nullptr_t is not handled!"); - case BuiltinType::ObjCId: case BuiltinType::ObjCClass: case BuiltinType::ObjCSel: @@ -270,8 +242,9 @@ static bool IsStandardLibraryRTTIDescriptor(QualType Ty) { /// 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(ASTContext &Context, - QualType Ty) { +static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) { + ASTContext &Context = CGM.getContext(); + // If RTTI is disabled, don't consider key functions. if (!Context.getLangOptions().RTTI) return false; @@ -283,13 +256,7 @@ static bool ShouldUseExternalRTTIDescriptor(ASTContext &Context, if (!RD->isDynamicClass()) return false; - // Get the key function. - const CXXMethodDecl *KeyFunction = Context.getKeyFunction(RD); - if (KeyFunction && !KeyFunction->hasBody()) { - // The class has a key function, but it is not defined in this translation - // unit, so we should use the external descriptor for it. - return true; - } + return !CGM.getVTables().ShouldEmitVTableInThisTU(RD); } return false; @@ -335,7 +302,8 @@ static bool ContainsIncompleteClassType(QualType Ty) { /// getTypeInfoLinkage - Return the linkage that the type info and type info /// name constants should have for the given type. -static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) { +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 @@ -355,16 +323,22 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) { return llvm::GlobalValue::InternalLinkage; case ExternalLinkage: + if (!CGM.getLangOptions().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<RecordType>(Ty)) { const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl()); if (RD->isDynamicClass()) - return CodeGenModule::getVTableLinkage(RD); + return CGM.getVTableLinkage(RD); } - return llvm::GlobalValue::WeakODRLinkage; + return llvm::GlobalValue::LinkOnceODRLinkage; } - return llvm::GlobalValue::WeakODRLinkage; + return llvm::GlobalValue::LinkOnceODRLinkage; } // CanUseSingleInheritance - Return whether the given record decl has a "single, @@ -513,23 +487,81 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) { Fields.push_back(VTable); } +// maybeUpdateRTTILinkage - Will update the linkage of the RTTI data structures +// from available_externally to the correct linkage if necessary. An example of +// this is: +// +// struct A { +// virtual void f(); +// }; +// +// const std::type_info &g() { +// return typeid(A); +// } +// +// void A::f() { } +// +// When we're generating the typeid(A) expression, we do not yet know that +// A's key function is defined in this translation unit, so we will give the +// typeinfo and typename structures available_externally linkage. When A::f +// forces the vtable to be generated, we need to change the linkage of the +// typeinfo and typename structs, otherwise we'll end up with undefined +// externals when linking. +static void +maybeUpdateRTTILinkage(CodeGenModule &CGM, llvm::GlobalVariable *GV, + QualType Ty) { + // We're only interested in globals with available_externally linkage. + if (!GV->hasAvailableExternallyLinkage()) + return; + + // Get the real linkage for the type. + llvm::GlobalVariable::LinkageTypes Linkage = getTypeInfoLinkage(CGM, Ty); + + // If variable is supposed to have available_externally linkage, we don't + // need to do anything. + if (Linkage == llvm::GlobalVariable::AvailableExternallyLinkage) + return; + + // Update the typeinfo linkage. + GV->setLinkage(Linkage); + + // Get the typename global. + llvm::SmallString<256> OutName; + llvm::raw_svector_ostream Out(OutName); + CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(Ty, Out); + Out.flush(); + llvm::StringRef Name = OutName.str(); + + llvm::GlobalVariable *TypeNameGV = CGM.getModule().getNamedGlobal(Name); + + assert(TypeNameGV->hasAvailableExternallyLinkage() && + "Type name has different linkage from type info!"); + + // And update its linkage. + TypeNameGV->setLinkage(Linkage); +} + llvm::Constant *RTTIBuilder::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. llvm::SmallString<256> OutName; - CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, OutName); + llvm::raw_svector_ostream Out(OutName); + CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out); + Out.flush(); llvm::StringRef Name = OutName.str(); - + llvm::GlobalVariable *OldGV = CGM.getModule().getNamedGlobal(Name); - if (OldGV && !OldGV->isDeclaration()) + if (OldGV && !OldGV->isDeclaration()) { + maybeUpdateRTTILinkage(CGM, OldGV, Ty); + return llvm::ConstantExpr::getBitCast(OldGV, Int8PtrTy); + } // Check if there is already an external RTTI descriptor for this type. bool IsStdLib = IsStandardLibraryRTTIDescriptor(Ty); - if (!Force && - (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM.getContext(), Ty))) + if (!Force && (IsStdLib || ShouldUseExternalRTTIDescriptor(CGM, Ty))) return GetAddrOfExternalRTTIDescriptor(Ty); // Emit the standard library with external linkage. @@ -537,13 +569,16 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { if (IsStdLib) Linkage = llvm::GlobalValue::ExternalLinkage; else - Linkage = getTypeInfoLinkage(Ty); + Linkage = getTypeInfoLinkage(CGM, Ty); // Add the vtable pointer. BuildVTablePointer(cast<Type>(Ty)); // And the name. - Fields.push_back(BuildName(Ty, DecideHidden(Ty), Linkage)); + llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); + + const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext); + Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, Int8PtrTy)); switch (Ty->getTypeClass()) { #define TYPE(Class, Base) @@ -641,13 +676,28 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { // type_infos themselves, so we can emit these as hidden symbols. // But don't do this if we're worried about strict visibility // compatibility. - if (const RecordType *RT = dyn_cast<RecordType>(Ty)) - CGM.setTypeVisibility(GV, cast<CXXRecordDecl>(RT->getDecl()), - /*ForRTTI*/ true); - else if (CGM.getCodeGenOpts().HiddenWeakVTables && - Linkage == llvm::GlobalValue::WeakODRLinkage) - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - + if (const RecordType *RT = dyn_cast<RecordType>(Ty)) { + const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); + + CGM.setTypeVisibility(GV, RD, CodeGenModule::TVK_ForRTTI); + CGM.setTypeVisibility(TypeName, RD, CodeGenModule::TVK_ForRTTIName); + } else { + Visibility TypeInfoVisibility = DefaultVisibility; + if (CGM.getCodeGenOpts().HiddenWeakVTables && + Linkage == llvm::GlobalValue::LinkOnceODRLinkage) + TypeInfoVisibility = HiddenVisibility; + + // The type name should have the same visibility as the type itself. + Visibility ExplicitVisibility = Ty->getVisibility(); + TypeName->setVisibility(CodeGenModule:: + GetLLVMVisibility(ExplicitVisibility)); + + TypeInfoVisibility = minVisibility(TypeInfoVisibility, Ty->getVisibility()); + GV->setVisibility(CodeGenModule::GetLLVMVisibility(TypeInfoVisibility)); + } + + GV->setUnnamedAddr(true); + return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); } @@ -701,12 +751,14 @@ void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) { Fields.push_back(BaseTypeInfo); } -/// SeenBases - Contains virtual and non-virtual bases seen when traversing -/// a class hierarchy. -struct SeenBases { - llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases; - llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases; -}; +namespace { + /// SeenBases - Contains virtual and non-virtual bases seen when traversing + /// a class hierarchy. + struct SeenBases { + llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases; + llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases; + }; +} /// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in /// abi::__vmi_class_type_info. @@ -827,7 +879,7 @@ void RTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { OffsetFlags = CGM.getVTables().getVirtualBaseOffsetOffset(RD, BaseDecl); else { const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); - OffsetFlags = Layout.getBaseClassOffset(BaseDecl) / 8; + OffsetFlags = Layout.getBaseClassOffsetInBits(BaseDecl) / 8; }; OffsetFlags <<= 8; @@ -938,16 +990,16 @@ void CodeGenModule::EmitFundamentalRTTIDescriptor(QualType Type) { } void CodeGenModule::EmitFundamentalRTTIDescriptors() { - QualType FundamentalTypes[] = { Context.VoidTy, Context.Char32Ty, - Context.Char16Ty, Context.UnsignedLongLongTy, - Context.LongLongTy, Context.WCharTy, - Context.UnsignedShortTy, Context.ShortTy, - Context.UnsignedLongTy, Context.LongTy, - Context.UnsignedIntTy, Context.IntTy, - Context.UnsignedCharTy, Context.FloatTy, - Context.LongDoubleTy, Context.DoubleTy, - Context.CharTy, Context.BoolTy, - Context.SignedCharTy }; + 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.FloatTy, + Context.DoubleTy, Context.LongDoubleTy, + Context.Char16Ty, Context.Char32Ty }; for (unsigned i = 0; i < sizeof(FundamentalTypes)/sizeof(QualType); ++i) EmitFundamentalRTTIDescriptor(FundamentalTypes[i]); } |