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

Dmitri Gribenko gribozavr at gmail.com
Sun Mar 30 07:18:36 PDT 2014


On Sun, Mar 30, 2014 at 12:34 PM, Tim Northover <tnorthover at apple.com> wrote:
> 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);}

I know this code was there before, but it looks like there is an
aliasing violation.  It would be better phrased as:

return reinterpret_cast<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

Spurious #if 1?  Also, this function (__name_for_load) seems to be
identical to name(), am I missing something?

Dmitri

-- 
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr at gmail.com>*/



More information about the cfe-commits mailing list