[libcxx] r205139 - ARM64: compare RTTI names as strings

Tim Northover tnorthover at apple.com
Sun Mar 30 04:34:26 PDT 2014


Author: tnorthover
Date: Sun Mar 30 06:34:26 2014
New Revision: 205139

URL: http://llvm.org/viewvc/llvm-project?rev=205139&view=rev
Log:
ARM64: compare RTTI names as strings

ARM64 generates RTTI with hidden visibility, which means that typeinfo
must be compared char-by-char since it's not guaranteed to be uniqued
across the whole program.

Modified:
    libcxx/trunk/include/__config
    libcxx/trunk/include/typeinfo

Modified: libcxx/trunk/include/__config
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__config?rev=205139&r1=205138&r2=205139&view=diff
==============================================================================
--- libcxx/trunk/include/__config (original)
+++ libcxx/trunk/include/__config Sun Mar 30 06:34:26 2014
@@ -568,6 +568,10 @@ template <unsigned> struct __static_asse
 #define _LIBCPP_EXTERN_TEMPLATE2(...) extern template __VA_ARGS__;
 #endif
 
+#if __APPLE__ && defined(__LP64__) && !defined(__x86_64__)
+#define _LIBCPP_NONUNIQUE_RTTI_BIT (1ULL << 63)
+#endif
+
 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(_WIN32) || defined(__sun__) || defined(__NetBSD__)
 #define _LIBCPP_LOCALE__L_EXTENSIONS 1
 #endif

Modified: libcxx/trunk/include/typeinfo
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/typeinfo?rev=205139&r1=205138&r2=205139&view=diff
==============================================================================
--- libcxx/trunk/include/typeinfo (original)
+++ libcxx/trunk/include/typeinfo Sun Mar 30 06:34:26 2014
@@ -60,6 +60,7 @@ public:
 #include <__config>
 #include <exception>
 #include <cstddef>
+#include <cstdint>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #pragma GCC system_header
@@ -73,32 +74,83 @@ class _LIBCPP_EXCEPTION_ABI type_info
     type_info& operator=(const type_info&);
     type_info(const type_info&);
 protected:
+#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT
     const char* __type_name;
+#else
+    // A const char* with the non-unique RTTI bit possibly set.
+    uintptr_t __type_name;
+#endif
 
     _LIBCPP_INLINE_VISIBILITY
     explicit type_info(const char* __n)
+#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT
         : __type_name(__n) {}
+#else
+        : __type_name(reinterpret_cast<uintptr_t>(__n)) {}
+#endif
 
 public:
     virtual ~type_info();
 
     _LIBCPP_INLINE_VISIBILITY
-    const char* name() const _NOEXCEPT {return __type_name;}
+    const char* name() const _NOEXCEPT
+#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT
+        {return __type_name;}
+#else
+        {return reinterpret_cast<const char*>(__type_name & ~_LIBCPP_NONUNIQUE_RTTI_BIT);}
+#endif
 
     _LIBCPP_INLINE_VISIBILITY
     bool before(const type_info& __arg) const _NOEXCEPT
+#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT
         {return __type_name < __arg.__type_name;}
+#else
+        {if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT))
+           return __type_name < __arg.__type_name;
+         return __compare_nonunique_names(__arg) < 0;}
+#endif
+
     _LIBCPP_INLINE_VISIBILITY
     size_t hash_code() const _NOEXCEPT
+#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT
         {return *reinterpret_cast<const size_t*>(&__type_name);}
+#else
+        {if (!(__type_name & _LIBCPP_NONUNIQUE_RTTI_BIT)) return __type_name;
+         const char *__ptr = __name_for_load();
+         size_t __hash = 5381;
+         while (unsigned char __c = static_cast<unsigned char>(*__ptr++))
+           __hash = (__hash * 33) ^ __c;
+         return __hash;}
+#endif
 
     _LIBCPP_INLINE_VISIBILITY
     bool operator==(const type_info& __arg) const _NOEXCEPT
+#ifndef _LIBCPP_NONUNIQUE_RTTI_BIT
         {return __type_name == __arg.__type_name;}
+#else
+        {if (__type_name == __arg.__type_name) return true;
+         if (!((__type_name & __arg.__type_name) & _LIBCPP_NONUNIQUE_RTTI_BIT))
+           return false;
+         return __compare_nonunique_names(__arg) == 0;}
+#endif
     _LIBCPP_INLINE_VISIBILITY
     bool operator!=(const type_info& __arg) const _NOEXCEPT
         {return !operator==(__arg);}
 
+#ifdef _LIBCPP_NONUNIQUE_RTTI_BIT
+  private:
+    _LIBCPP_INLINE_VISIBILITY
+    int __compare_nonunique_names(const type_info &__arg) const _NOEXCEPT
+        {return __builtin_strcmp(__name_for_load(), __arg.__name_for_load());}
+
+    _LIBCPP_INLINE_VISIBILITY
+    const char *__name_for_load() const _NOEXCEPT
+        {uintptr_t __data = __type_name;
+#if 1
+         __data &= ~_LIBCPP_NONUNIQUE_RTTI_BIT;
+#endif
+         return reinterpret_cast<const char*>(__data);}
+#endif
 };
 
 class _LIBCPP_EXCEPTION_ABI bad_cast





More information about the cfe-commits mailing list