Index: support.h
===================================================================
--- support.h	(revision 191815)
+++ support.h	(working copy)
@@ -15,8 +15,19 @@
    Functions and constants used in libc++ that are missing from the Windows C library.
   */
 
+#if !defined(_MSC_VER) || defined(__clang__)
+#pragma GCC system_header
+#endif
+
 #include <wchar.h>  // mbstate_t
 #include <cstdarg> // va_ macros
+#include <stdint.h> // uint32_t
+#if defined(_LIBCPP_MSVCRT)
+#include <xlocinfo.h> // _Stof etc.
+#endif
+#include <intrin.h> // _BitScanForward64 etc.
+#include <limits> // std::numeric_limits::digits
+
 #define swprintf _snwprintf
 #define vswprintf _vsnwprintf
 
@@ -37,12 +48,16 @@
 
 #if defined(_LIBCPP_MSVCRT)
 #define snprintf _snprintf
-#include <xlocinfo.h>
 #define atoll _atoi64
 #define strtoll _strtoi64
 #define strtoull _strtoui64
 #define wcstoll _wcstoi64
 #define wcstoull _wcstoui64
+// FIXME! Why not remove this reference to _Exit here and in
+// cstdlib for Windows if libcxx itself doesn't use it?
+#define _Exit _exit
+
+// _Stof etc. found in <xlockinfo.h>
 _LIBCPP_ALWAYS_INLINE float strtof( const char *nptr, char **endptr )
 { return _Stof(nptr, endptr, 0); }
 _LIBCPP_ALWAYS_INLINE double strtod( const char *nptr, char **endptr )
@@ -50,10 +65,13 @@
 _LIBCPP_ALWAYS_INLINE long double strtold( const char *nptr, char **endptr )
 { return _Stold(nptr, endptr, 0); }
 
-#define _Exit _exit
+// clang && gcc support these intrinsics.
+#if defined(_LIBCPP_MSVC)
 
-#ifndef __clang__ // MSVC-based Clang also defines _MSC_VER
-#include <intrin.h>
+// FIXME. I think these routines could be used here:
+// http://msdn.microsoft.com/en-us/library/bb385231%28v=vs.90%29.aspx
+// For SSE4 targets this could be used instead:
+// http://msdn.microsoft.com/en-us/library/bb531475%28v=VS.90%29.aspx
 
 _LIBCPP_ALWAYS_INLINE int __builtin_popcount(unsigned int x) {
    static const unsigned int m1 = 0x55555555; //binary: 0101...
@@ -81,39 +99,96 @@
    return static_cast<int>((x * h01)>>56);  //returns left 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ...
 }
 
-_LIBCPP_ALWAYS_INLINE int __builtin_ctz( unsigned int x )
+// The_BitScanForward64 and _BitScanReverse64 intrinsics do not
+// currently exist in the MS 32 bit compiler. However it would be
+// useful since the 32 bit compiler supports 64 bit data types.
+// Implement these 64 bit intrinsics in terms of their 32 bit
+// counter parts when in 64 bit mode.
+
+// Note that the offset returned is from the LSB.
+_LIBCPP_ALWAYS_INLINE unsigned char _libcpp_bsf64( unsigned long* index, uint64_t mask ) _NOEXCEPT
 {
-   DWORD r = 0;
-   _BitScanReverse(&r, x);
-   return static_cast<int>(r);
+#if defined(_WIN64)
+    return _BitScanForward64(index, mask);
+#elif defined(_WIN32)
+    const uint32_t low = mask & 0x00000000FFFFFFFF; // Low order 32 bits.
+    unsigned char ret =_BitScanForward(index, low);
+    if (ret)
+        return ret;
+    const uint32_t high = mask >> 32; // High order 32 bits.
+    ret = _BitScanForward(index, high);
+    if (ret)
+        *index += 32; // Create a bit offset from the LSB.
+    return ret;
+#else
+#   error "Implementation of _libcpp_bsf64 required"
+#endif
 }
 
+// Implementation of _BitScanReverse64 implemented in terms
+// of two _BitScanReverse 32 bit operations. See comment above.
+// Note that the offset returned is from the LSB.
+_LIBCPP_ALWAYS_INLINE unsigned char _libcpp_bsr64( unsigned long* index, uint64_t mask ) _NOEXCEPT
+{
+#if defined(_WIN64)
+    return _BitScanReverse64(index, mask);
+#elif defined(_WIN32)
+    const uint32_t high = mask >> 32; // High order 32 bits.
+    unsigned char ret =_BitScanReverse(index, high);
+    if (ret) {
+        *index += 32; // Create a bit offset from the MSB.
+        return ret;
+    }
+    const uint32_t low = mask & 0x00000000FFFFFFFF;
+    ret = _BitScanReverse(index, low);
+    return ret;    
+#else
+#   error "Implementation of _libcpp_bsr64 required"
+#endif
+}
+
 // sizeof(long) == sizeof(int) on Windows
+_LIBCPP_ALWAYS_INLINE int __builtin_ctzll( unsigned long long x )
+{
+    unsigned long where;
+    _libcpp_bsf64(&where, x);
+    return static_cast<int>(where);
+}
+
 _LIBCPP_ALWAYS_INLINE int __builtin_ctzl( unsigned long x )
-{ return __builtin_ctz( static_cast<int>(x) ); }
+{
+    unsigned long where;
+    _BitScanReverse(&where, x);
+    return static_cast<int>(where);
+}
 
-_LIBCPP_ALWAYS_INLINE int __builtin_ctzll( unsigned long long x )
+_LIBCPP_ALWAYS_INLINE int __builtin_ctz( unsigned int x )
 {
-    DWORD r = 0;
-    _BitScanReverse64(&r, x);
-    return static_cast<int>(r);
+    return __builtin_ctzl( x );
 }
-_LIBCPP_ALWAYS_INLINE int __builtin_clz( unsigned int x )
+
+_LIBCPP_ALWAYS_INLINE int __builtin_clzll( unsigned long long x )
 {
-   DWORD r = 0;
-   _BitScanForward(&r, x);
-   return static_cast<int>(r);
+    unsigned long where;
+    _libcpp_bsr64(&where, x);
+    const int msbit = std::numeric_limits<unsigned long long>::digits - 1;
+    return static_cast<int>(msbit - where);
 }
+
 // sizeof(long) == sizeof(int) on Windows
 _LIBCPP_ALWAYS_INLINE int __builtin_clzl( unsigned long x )
-{ return __builtin_clz( static_cast<int>(x) ); }
-_LIBCPP_ALWAYS_INLINE int __builtin_clzll( unsigned long long x )
 {
-    DWORD r = 0;
-    _BitScanForward64(&r, x);
-    return static_cast<int>(r);
+    unsigned long where;
+    _BitScanForward(&where, x);
+    const int msbit = std::numeric_limits<unsigned long>::digits - 1;
+    return static_cast<int>(msbit - where);
 }
-#endif // !__clang__
+
+_LIBCPP_ALWAYS_INLINE int __builtin_clz( unsigned int x )
+{
+    return __builtin_clzl(x);
+}
+
+#endif // _LIBCPP_MSVC
 #endif // _LIBCPP_MSVCRT
-
 #endif // _LIBCPP_SUPPORT_WIN32_SUPPORT_H
