r205101 - CodeGen: Allow different RTTI emission strategies

Tim Northover tnorthover at apple.com
Sat Mar 29 08:09:55 PDT 2014


Author: tnorthover
Date: Sat Mar 29 10:09:55 2014
New Revision: 205101

URL: http://llvm.org/viewvc/llvm-project?rev=205101&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/CodeGen/CGRTTI.cpp

Modified: cfe/trunk/lib/CodeGen/CGRTTI.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGRTTI.cpp?rev=205101&r1=205100&r2=205101&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGRTTI.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGRTTI.cpp Sat Mar 29 10:09:55 2014
@@ -508,6 +508,52 @@ void RTTIBuilder::BuildVTablePointer(con
   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::BuildTypeIn
   
   // And the name.
   llvm::GlobalVariable *TypeName = GetAddrOfTypeName(Ty, Linkage);
+  llvm::Constant *typeNameField;
 
-  Fields.push_back(llvm::ConstantExpr::getBitCast(TypeName, CGM.Int8PtrTy));
+  // 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::BuildTypeIn
   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);
 }
 





More information about the cfe-commits mailing list