summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r--clang/lib/CodeGen/CGRTTI.cpp72
1 files changed, 70 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGRTTI.cpp b/clang/lib/CodeGen/CGRTTI.cpp
index e398cd47fd0..c33f088f3c8 100644
--- a/clang/lib/CodeGen/CGRTTI.cpp
+++ b/clang/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);
}
OpenPOWER on IntegriCloud