2 * Copyright Andrey Semashev 2007 - 2015.
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
9 * \author Andrey Semashev
12 * \brief This header is the Boost.Log library implementation, see the library documentation
13 * at http://www.boost.org/doc/libs/release/libs/log/doc/html/index.html.
16 #include <boost/log/detail/config.hpp>
18 #include <boost/cstdint.hpp>
19 #include <boost/log/utility/manipulators/dump.hpp>
20 #if defined(_MSC_VER) && (defined(BOOST_LOG_USE_SSSE3) || defined(BOOST_LOG_USE_AVX2))
21 #include <boost/winapi/dll.hpp>
22 #include <intrin.h> // __cpuid
24 #include <boost/log/detail/header.hpp>
28 BOOST_LOG_OPEN_NAMESPACE
32 #if defined(BOOST_LOG_USE_SSSE3)
33 extern dump_data_char_t dump_data_char_ssse3
;
34 extern dump_data_wchar_t dump_data_wchar_ssse3
;
35 #if !defined(BOOST_NO_CXX11_CHAR16_T)
36 extern dump_data_char16_t dump_data_char16_ssse3
;
38 #if !defined(BOOST_NO_CXX11_CHAR32_T)
39 extern dump_data_char32_t dump_data_char32_ssse3
;
42 #if defined(BOOST_LOG_USE_AVX2)
43 extern dump_data_char_t dump_data_char_avx2
;
44 extern dump_data_wchar_t dump_data_wchar_avx2
;
45 #if !defined(BOOST_NO_CXX11_CHAR16_T)
46 extern dump_data_char16_t dump_data_char16_avx2
;
48 #if !defined(BOOST_NO_CXX11_CHAR32_T)
49 extern dump_data_char32_t dump_data_char32_avx2
;
53 enum { stride
= 256 };
55 extern const char g_hex_char_table
[2][16] =
57 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' },
58 { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }
61 template< typename CharT
>
62 void dump_data_generic(const void* data
, std::size_t size
, std::basic_ostream
< CharT
>& strm
)
64 typedef CharT char_type
;
66 char_type buf
[stride
* 3u];
68 const char* const char_table
= g_hex_char_table
[(strm
.flags() & std::ios_base::uppercase
) != 0];
69 const std::size_t stride_count
= size
/ stride
, tail_size
= size
% stride
;
71 const uint8_t* p
= static_cast< const uint8_t* >(data
);
72 char_type
* buf_begin
= buf
+ 1u; // skip the first space of the first chunk
73 char_type
* buf_end
= buf
+ sizeof(buf
) / sizeof(*buf
);
75 for (std::size_t i
= 0; i
< stride_count
; ++i
)
78 for (unsigned int j
= 0; j
< stride
; ++j
, b
+= 3u, ++p
)
81 b
[0] = static_cast< char_type
>(' ');
82 b
[1] = static_cast< char_type
>(char_table
[n
>> 4]);
83 b
[2] = static_cast< char_type
>(char_table
[n
& 0x0F]);
86 strm
.write(buf_begin
, buf_end
- buf_begin
);
97 b
[0] = static_cast< char_type
>(' ');
98 b
[1] = static_cast< char_type
>(char_table
[n
>> 4]);
99 b
[2] = static_cast< char_type
>(char_table
[n
& 0x0F]);
104 while (i
< tail_size
);
106 strm
.write(buf_begin
, b
- buf_begin
);
110 BOOST_LOG_API dump_data_char_t
* dump_data_char
= &dump_data_generic
< char >;
111 BOOST_LOG_API dump_data_wchar_t
* dump_data_wchar
= &dump_data_generic
< wchar_t >;
112 #if !defined(BOOST_NO_CXX11_CHAR16_T)
113 BOOST_LOG_API dump_data_char16_t
* dump_data_char16
= &dump_data_generic
< char16_t
>;
115 #if !defined(BOOST_NO_CXX11_CHAR32_T)
116 BOOST_LOG_API dump_data_char32_t
* dump_data_char32
= &dump_data_generic
< char32_t
>;
119 #if defined(BOOST_LOG_USE_SSSE3) || defined(BOOST_LOG_USE_AVX2)
121 BOOST_LOG_ANONYMOUS_NAMESPACE
{
123 struct function_pointer_initializer
125 function_pointer_initializer()
127 // First, let's check for the max supported cpuid function
128 uint32_t eax
= 0, ebx
= 0, ecx
= 0, edx
= 0;
129 cpuid(eax
, ebx
, ecx
, edx
);
131 const uint32_t max_cpuid_function
= eax
;
132 if (max_cpuid_function
>= 1)
136 cpuid(eax
, ebx
, ecx
, edx
);
138 // Check for SSSE3 support
142 #if defined(BOOST_LOG_USE_AVX2)
143 if (max_cpuid_function
>= 7)
145 // To check for AVX2 availability we also need to verify that OS supports it
146 // Check that OSXSAVE is supported by CPU
147 if (ecx
& (1u << 27))
149 // Check that it is used by the OS
150 bool mmstate
= false;
151 #if defined(__GNUC__)
152 // Get the XFEATURE_ENABLED_MASK register
156 : "=a" (eax
), "=d" (edx
)
159 mmstate
= (eax
& 6U) == 6U;
160 #elif defined(BOOST_WINDOWS)
161 // MSVC does not have an intrinsic for xgetbv, we have to query OS
162 boost::winapi::HMODULE_ hKernel32
= boost::winapi::GetModuleHandleW(L
"kernel32.dll");
165 typedef uint64_t (BOOST_WINAPI_WINAPI_CC
* get_enabled_extended_features_t
)(uint64_t);
166 get_enabled_extended_features_t get_enabled_extended_features
= (get_enabled_extended_features_t
)boost::winapi::get_proc_address(hKernel32
, "GetEnabledExtendedFeatures");
167 if (get_enabled_extended_features
)
169 // XSTATE_MASK_LEGACY_SSE | XSTATE_MASK_GSSE == 6
170 mmstate
= get_enabled_extended_features(6u) == 6u;
177 // Finally, check for AVX2 support in CPU
180 cpuid(eax
, ebx
, ecx
, edx
);
187 #endif // defined(BOOST_LOG_USE_AVX2)
192 static void cpuid(uint32_t& eax
, uint32_t& ebx
, uint32_t& ecx
, uint32_t& edx
)
194 #if defined(__GNUC__)
195 #if (defined(__i386__) || defined(__VXWORKS__)) && (defined(__PIC__) || defined(__PIE__)) && !(defined(__clang__) || (defined(BOOST_GCC) && BOOST_GCC >= 50100))
196 // Unless the compiler can do it automatically, we have to backup ebx in 32-bit PIC/PIE code because it is reserved by the ABI.
197 // For VxWorks ebx is reserved on 64-bit as well.
198 #if defined(__x86_64__)
202 "xchgq %%rbx, %0\n\t"
204 "xchgq %%rbx, %0\n\t"
205 : "+DS" (rbx
), "+a" (eax
), "+c" (ecx
), "+d" (edx
)
207 ebx
= static_cast< uint32_t >(rbx
);
208 #else // defined(__x86_64__)
211 "xchgl %%ebx, %0\n\t"
213 "xchgl %%ebx, %0\n\t"
214 : "+DS" (ebx
), "+a" (eax
), "+c" (ecx
), "+d" (edx
)
216 #endif // defined(__x86_64__)
221 : "+a" (eax
), "+b" (ebx
), "+c" (ecx
), "+d" (edx
)
224 #elif defined(_MSC_VER)
232 #error Boost.Log: Unexpected compiler
236 static void enable_ssse3()
238 dump_data_char
= &dump_data_char_ssse3
;
239 dump_data_wchar
= &dump_data_wchar_ssse3
;
240 #if !defined(BOOST_NO_CXX11_CHAR16_T)
241 dump_data_char16
= &dump_data_char16_ssse3
;
243 #if !defined(BOOST_NO_CXX11_CHAR32_T)
244 dump_data_char32
= &dump_data_char32_ssse3
;
248 #if defined(BOOST_LOG_USE_AVX2)
249 static void enable_avx2()
251 dump_data_char
= &dump_data_char_avx2
;
252 dump_data_wchar
= &dump_data_wchar_avx2
;
253 #if !defined(BOOST_NO_CXX11_CHAR16_T)
254 dump_data_char16
= &dump_data_char16_avx2
;
256 #if !defined(BOOST_NO_CXX11_CHAR32_T)
257 dump_data_char32
= &dump_data_char32_avx2
;
260 #endif // defined(BOOST_LOG_USE_AVX2)
263 static function_pointer_initializer g_function_pointer_initializer
;
267 #endif // defined(BOOST_LOG_USE_SSSE3) || defined(BOOST_LOG_USE_AVX2)
271 BOOST_LOG_CLOSE_NAMESPACE
// namespace log
275 #include <boost/log/detail/footer.hpp>