From b8064edb9b71881ec314b1ca2654f06de4dc8fb3 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Sat, 29 Mar 2014 15:09:55 +0000 Subject: [PATCH] CodeGen: Allow different RTTI emission strategies Some ABIs and C++ libraries may make different trade-offs in how RTTI is emitted (currently with respect to visibility and so on). This implements one scheme, as used by ARM64. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205101 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGRTTI.cpp | 72 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp index e398cd47fd..c33f088f3c 100644 --- a/lib/CodeGen/CGRTTI.cpp +++ b/lib/CodeGen/CGRTTI.cpp @@ -508,6 +508,52 @@ void RTTIBuilder::BuildVTablePointer(const Type *Ty) { Fields.push_back(VTable); } +/// What sort of unique-RTTI behavior should we use? +enum UniqueRTTIKind { + /// We are guaranteeing, or need to guarantee, that the RTTI string + /// is unique. + UniqueRTTI, + + /// We are not guaranteeing uniqueness for the RTTI string, so we + /// can demote to hidden visibility and use string comparisons. + NonUniqueHiddenRTTI, + + /// 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. + NonUniqueVisibleRTTI +}; + +/// What sort of uniqueness rules should we use for the RTTI for the +/// given type? +static UniqueRTTIKind +classifyUniqueRTTI(CodeGenModule &CGM, QualType canTy, + llvm::GlobalValue::LinkageTypes linkage) { + // We only support non-unique RTTI on iOS64. + // FIXME: abstract this into CGCXXABI after this code moves to trunk. + if (CGM.getTarget().getCXXABI().getKind() != TargetCXXABI::iOS64) + return UniqueRTTI; + + // It's only necessary for linkonce_odr or weak_odr linkage. + if (linkage != llvm::GlobalValue::LinkOnceODRLinkage && + linkage != llvm::GlobalValue::WeakODRLinkage) + return UniqueRTTI; + + // It's only necessary with default visibility. + if (canTy->getVisibility() != DefaultVisibility) + return UniqueRTTI; + + // If we're not required to publish this symbol, hide it. + if (linkage == llvm::GlobalValue::LinkOnceODRLinkage) + return NonUniqueHiddenRTTI; + + // 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 NonUniqueVisibleRTTI; +} + llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { // We want to operate on the canonical type. Ty = CGM.getContext().getCanonicalType(Ty); @@ -544,8 +590,24 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { // And the name. llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage); - - Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy)); + 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. + UniqueRTTIKind uniqueRTTI = classifyUniqueRTTI(CGM, Ty, Linkage); + if (uniqueRTTI != UniqueRTTI) { + // 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) @@ -667,6 +729,12 @@ llvm::Constant *RTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) { TypeName->setVisibility(llvmVisibility); GV->setVisibility(llvmVisibility); + // FIXME: integrate this better into the above when we move to trunk + if (uniqueRTTI == NonUniqueHiddenRTTI) { + TypeName->setVisibility(llvm::GlobalValue::HiddenVisibility); + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); + } + return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); } -- 2.40.0