compnerd created this revision. compnerd added reviewers: EricWF, mclow.lists, majnemer, rnk. compnerd added subscribers: smeenai, kastiglione, cfe-commits. compnerd set the repository for this revision to rL LLVM.
The RTTI structure is different on Windows when building under MS ABI. Update the definition to reflect this. The structure itself contains an area for caching the undecorated name (which is 0-initialized). The decorated name has a bitfield followed by the linkage name. When std::type_info::name is invoked for the first time, the runtime should undecorate the name, cache it, and return the undecorated name. This requires access to an implementation of `__unDName`. For now, return the raw name. This uses the fnv-1a hash to hash the name of the RTTI. We could use an alternate hash (murmur? city?), but, this was the quickest to throw together. Repository: rL LLVM https://reviews.llvm.org/D28212 Files: include/typeinfo src/typeinfo.cpp
Index: src/typeinfo.cpp =================================================================== --- src/typeinfo.cpp +++ src/typeinfo.cpp @@ -15,6 +15,44 @@ #include "typeinfo" +#if defined(_WIN32) +#include <string.h> + +const char *std::type_info::name(std::type_info::data *__data) { + // TODO(compnerd) cache demangled &__data.__decorated_name[1] + return &__data->__decorated_name[1]; +} + +size_t std::type_info::hash(const std::type_info::data *__data) { +#if defined(_WIN64) + static constexpr const size_t fnv_offset_basis = 14695981039346656037; + static constexpr const size_t fnv_prime = 10995116282110; +#else + static constexpr const size_t fnv_offset_basis = 2166136261; + static constexpr const size_t fnv_prime = 16777619; +#endif + + size_t value = fnv_offset_basis; + for (const char *c = &__data->__decorated_name[1]; *c; ++c) { + value ^= static_cast<size_t>(static_cast<unsigned char>(*c)); + value *= fnv_prime; + } + +#if defined(_WIN64) + value ^= value >> 32; +#endif + + return value; +} + +int std::type_info::compare(const std::type_info::data *__lhs, + const std::type_info::data *__rhs) { + if (__lhs == __rhs) + return 0; + return strcmp(&__lhs->__decorated_name[1], &__rhs->__decorated_name[1]); +} +#endif + #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) std::type_info::~type_info() Index: include/typeinfo =================================================================== --- include/typeinfo +++ include/typeinfo @@ -72,6 +72,49 @@ namespace std // purposefully not using versioning namespace { +#if defined(_WIN32) +class _LIBCPP_EXCEPTION_ABI type_info +{ + type_info & operator=(const type_info &) _LIBCPP_EQUAL_DELETE; + type_info (const type_info &) _LIBCPP_EQUAL_DELETE; + + mutable struct data { + const char *__undecorated_name; + const char __decorated_name[1]; + } __data; + + static const char *name(type_info::data *__data); + static size_t hash(const type_info::data *__data); + static int compare(const type_info::data *__l, const type_info::data *__r); + +public: + virtual ~type_info() _NOEXCEPT; + + _LIBCPP_INLINE_VISIBILITY + const char *name() const _NOEXCEPT { + return name(&__data); + } + + _LIBCPP_INLINE_VISIBILITY + bool before(const type_info &__arg) const _NOEXCEPT { + return compare(&__data, &__arg.__data) < 0; + } + + _LIBCPP_INLINE_VISIBILITY + size_t hash_code() const _NOEXCEPT { + return hash(&__data); + } + + _LIBCPP_INLINE_VISIBILITY + bool operator==(const type_info &__arg) const _NOEXCEPT { + return compare(&__data, &__arg.__data) == 0; + } + + bool operator!=(const type_info &__arg) const _NOEXCEPT { + return compare(&__data, &__arg.__data) != 0; + } +}; +#else class _LIBCPP_EXCEPTION_ABI type_info { type_info& operator=(const type_info&); @@ -148,6 +191,7 @@ {return __builtin_strcmp(name(), __arg.name());} #endif }; +#endif class _LIBCPP_EXCEPTION_ABI bad_cast : public exception
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits