diff options
Diffstat (limited to 'lib/CodeGen/CGRTTI.cpp')
-rw-r--r-- | lib/CodeGen/CGRTTI.cpp | 109 |
1 files changed, 57 insertions, 52 deletions
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index ff7e27336b..b91cc8cf41 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -37,8 +37,12 @@ class RTTIBuilder { /// BuildVtablePointer - Build the vtable pointer for the given type. void BuildVtablePointer(const Type *Ty); - /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, - /// used for pointer types. + /// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single + /// inheritance, according to the Itanium C++ ABI, 2.95p6b. + void BuildSIClassTypeInfo(const CXXRecordDecl *RD); + + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, used + /// for pointer types. void BuildPointerTypeInfo(const PointerType *Ty); /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info @@ -262,33 +266,6 @@ public: return llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), n); } - // FIXME: unify with getTypeInfoLinkage - bool DecideExtern(QualType Ty) { - // For this type, see if all components are never in an anonymous namespace. - if (const MemberPointerType *MPT = Ty->getAs<MemberPointerType>()) - return (DecideExtern(MPT->getPointeeType()) - && DecideExtern(QualType(MPT->getClass(), 0))); - if (const PointerType *PT = Ty->getAs<PointerType>()) - return DecideExtern(PT->getPointeeType()); - if (const FunctionType *FT = Ty->getAs<FunctionType>()) { - if (DecideExtern(FT->getResultType()) == false) - return false; - if (const FunctionProtoType *FPT = Ty->getAs<FunctionProtoType>()) { - for (unsigned i = 0; i <FPT->getNumArgs(); ++i) - if (DecideExtern(FPT->getArgType(i)) == false) - return false; - for (unsigned i = 0; i <FPT->getNumExceptions(); ++i) - if (DecideExtern(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 !RD->isInAnonymousNamespace() && RD->hasLinkage(); - return true; - } - // FIXME: unify with DecideExtern bool DecideHidden(QualType Ty) { // For this type, see if all components are never hidden. @@ -316,27 +293,6 @@ public: return false; } - llvm::Constant *BuildSimpleType(QualType Ty, const char *vtbl) { - llvm::SmallString<256> OutName; - CGM.getMangleContext().mangleCXXRTTI(Ty, OutName); - llvm::StringRef Name = OutName.str(); - - llvm::GlobalVariable *GV; - GV = CGM.getModule().getNamedGlobal(Name); - if (GV && !GV->isDeclaration()) - return llvm::ConstantExpr::getBitCast(GV, Int8PtrTy); - - bool Extern = DecideExtern(Ty); - bool Hidden = DecideHidden(Ty); - - Info.push_back(BuildVtableRef(vtbl)); - Info.push_back(BuildName(Ty, Hidden, Extern)); - - // We always generate these as hidden, only the name isn't hidden. - return finish(GV, Name, /*Hidden=*/Extern ? true : false, - GetLinkageFromExternFlag(Extern)); - } - /// BuildType - Builds the type info for the given type. llvm::Constant *BuildType(QualType Ty) { const clang::Type &Type @@ -357,7 +313,7 @@ public: const RecordType *RT = cast<RecordType>(&Type); const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - if (RD->getNumBases()) + if (RD->getNumBases() != 0 && !SimpleInheritance(RD)) return BuildClassTypeInfo(RD); // Fall through. @@ -685,6 +641,35 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(QualType Ty) { return llvm::GlobalValue::WeakODRLinkage; } +// 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<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl()); + if (!BaseDecl->isEmpty() && + BaseDecl->isDynamicClass() != RD->isDynamicClass()) + return false; + + return true; +} + void RTTIBuilder::BuildVtablePointer(const Type *Ty) { const char *VtableName; @@ -721,8 +706,14 @@ void RTTIBuilder::BuildVtablePointer(const Type *Ty) { if (!RD->getNumBases()) { // abi::__class_type_info VtableName = "_ZTVN10__cxxabiv117__class_type_infoE"; - break; + } else if (CanUseSingleInheritance(RD)) { + // abi::__si_class_type_info; + VtableName = "_ZTVN10__cxxabiv120__si_class_type_infoE"; + } else { + assert(false && "Should not get here!"); } + + break; } case Type::Pointer: @@ -812,6 +803,11 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty) { // We don't need to emit any fields. break; } + + if (CanUseSingleInheritance(RD)) { + BuildSIClassTypeInfo(RD); + break; + } } case Type::Pointer: @@ -858,6 +854,15 @@ static unsigned DetermineQualifierFlags(Qualifiers Quals) { return Flags; } +/// BuildSIClassTypeInfo - Build an abi::__si_class_type_info, used for single +/// inheritance, according to the Itanium C++ ABI, 2.95p6b. +void RTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) { + // 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, + Info.push_back(RTTIBuilder(CGM).BuildType(RD->bases_begin()->getType())); +} + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, /// used for pointer types. void RTTIBuilder::BuildPointerTypeInfo(const PointerType *Ty) { |