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

Reply via email to