/* * Copyright 2016 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef WABT_CONFIG_H_ #define WABT_CONFIG_H_ /* TODO(binji): nice way to define these with WABT_ prefix? */ /* Whether is available */ #cmakedefine01 HAVE_ALLOCA_H /* Whether is available */ #cmakedefine01 HAVE_UNISTD_H /* Whether snprintf is defined by stdio.h */ #cmakedefine01 HAVE_SNPRINTF /* Whether sysconf is defined by unistd.h */ #cmakedefine01 HAVE_SYSCONF /* Whether ssize_t is defined by stddef.h */ #cmakedefine01 HAVE_SSIZE_T /* Whether strcasecmp is defined by strings.h */ #cmakedefine01 HAVE_STRCASECMP /* Whether ENABLE_VIRTUAL_TERMINAL_PROCESSING is defined by windows.h */ #cmakedefine01 HAVE_WIN32_VT100 #cmakedefine01 COMPILER_IS_CLANG #cmakedefine01 COMPILER_IS_GNU #cmakedefine01 COMPILER_IS_MSVC #cmakedefine01 WITH_EXCEPTIONS #define SIZEOF_SIZE_T @SIZEOF_SIZE_T@ #define SIZEOF_INT @SIZEOF_INT@ #define SIZEOF_LONG @SIZEOF_LONG@ #define SIZEOF_LONG_LONG @SIZEOF_LONG_LONG@ #if HAVE_ALLOCA_H #include #elif COMPILER_IS_MSVC #include #define alloca _alloca #elif defined(__MINGW32__) #include #elif defined(__FreeBSD__) #include #else #error no alloca #endif #if COMPILER_IS_CLANG || COMPILER_IS_GNU #define WABT_UNUSED __attribute__ ((unused)) #define WABT_WARN_UNUSED __attribute__ ((warn_unused_result)) #define WABT_INLINE inline #define WABT_UNLIKELY(x) __builtin_expect(!!(x), 0) #define WABT_LIKELY(x) __builtin_expect(!!(x), 1) #if __MINGW32__ // mingw defaults to printf format specifier being ms_printf (which doesn't // understand 'llu', etc.) We always want gnu_printf, and force mingw to always // use mingw_printf, mingw_vprintf, etc. #define WABT_PRINTF_FORMAT(format_arg, first_arg) \ __attribute__((format(gnu_printf, (format_arg), (first_arg)))) #else #define WABT_PRINTF_FORMAT(format_arg, first_arg) \ __attribute__((format(printf, (format_arg), (first_arg)))) #endif #ifdef __cplusplus #if __cplusplus >= 201103L #define WABT_STATIC_ASSERT(x) static_assert((x), #x) #else #define WABT_STATIC_ASSERT__(x, c) \ static int static_assert_##c[(x ? 0 : -1)] WABT_UNUSED #define WABT_STATIC_ASSERT_(x, c) WABT_STATIC_ASSERT__(x, c) #define WABT_STATIC_ASSERT(x) WABT_STATIC_ASSERT_(x, __COUNTER__) #endif #else #define WABT_STATIC_ASSERT(x) _Static_assert((x), #x) #endif #if SIZEOF_INT == 4 #define wabt_clz_u32(x) __builtin_clz(x) #define wabt_ctz_u32(x) __builtin_ctz(x) #define wabt_popcount_u32(x) __builtin_popcount(x) #elif SIZEOF_LONG == 4 #define wabt_clz_u32(x) __builtin_clzl(x) #define wabt_ctz_u32(x) __builtin_ctzl(x) #define wabt_popcount_u32(x) __builtin_popcountl(x) #else #error "don't know how to define 32-bit builtins" #endif #if SIZEOF_LONG == 8 #define wabt_clz_u64(x) __builtin_clzl(x) #define wabt_ctz_u64(x) __builtin_ctzl(x) #define wabt_popcount_u64(x) __builtin_popcountl(x) #elif SIZEOF_LONG_LONG == 8 #define wabt_clz_u64(x) __builtin_clzll(x) #define wabt_ctz_u64(x) __builtin_ctzll(x) #define wabt_popcount_u64(x) __builtin_popcountll(x) #else #error "don't know how to define 64-bit builtins" #endif #define WABT_UNREACHABLE __builtin_unreachable() #elif COMPILER_IS_MSVC #include #include #define WABT_UNUSED #define WABT_WARN_UNUSED _Check_return_ #define WABT_INLINE __inline #define WABT_STATIC_ASSERT(x) _STATIC_ASSERT(x) #define WABT_UNLIKELY(x) (x) #define WABT_LIKELY(x) (x) #define WABT_PRINTF_FORMAT(format_arg, first_arg) #define WABT_UNREACHABLE __assume(0) __inline unsigned long wabt_clz_u32(unsigned long mask) { unsigned long index; _BitScanReverse(&index, mask); return sizeof(unsigned long) * 8 - (index + 1); } __inline unsigned long wabt_clz_u64(unsigned __int64 mask) { #if _M_X64 unsigned long index; _BitScanReverse64(&index, mask); return sizeof(unsigned __int64) * 8 - (index + 1); #elif _M_IX86 unsigned long index; unsigned long high_mask; memcpy(&high_mask, (unsigned char*)&mask + sizeof(unsigned long), sizeof(unsigned long)); if (_BitScanReverse(&index, high_mask)) { return sizeof(unsigned long) * 8 - (index + 1); } unsigned long low_mask; memcpy(&low_mask, &mask, sizeof(unsigned long)); _BitScanReverse(&index, low_mask); return sizeof(unsigned __int64) * 8 - (index + 1); #else #error unexpected architecture #endif } __inline unsigned long wabt_ctz_u32(unsigned long mask) { unsigned long index; _BitScanForward(&index, mask); return index; } __inline unsigned long wabt_ctz_u64(unsigned __int64 mask) { #if _M_X64 unsigned long index; _BitScanForward64(&index, mask); return index; #elif _M_IX86 unsigned long low_mask = (unsigned long)mask; if (low_mask) { return wabt_ctz_u32(low_mask); } unsigned long high_mask; memcpy(&high_mask, (unsigned char*)&mask + sizeof(unsigned long), sizeof(unsigned long)); return sizeof(unsigned long) * 8 + wabt_ctz_u32(high_mask); #else #error unexpected architecture #endif } #define wabt_popcount_u32 __popcnt #if _M_X64 #elif _M_IX86 __inline unsigned __int64 __popcnt64(unsigned __int64 value) { unsigned long high_value; unsigned long low_value; memcpy(&high_value, (unsigned char*)&value + sizeof(unsigned long), sizeof(unsigned long)); memcpy(&low_value, &value, sizeof(unsigned long)); return wabt_popcount_u32(high_value) + wabt_popcount_u32(low_value); } #else #error unexpected architecture #endif #define wabt_popcount_u64 __popcnt64 #else #error unknown compiler #endif #if COMPILER_IS_MSVC /* print format specifier for size_t */ #if SIZEOF_SIZE_T == 4 #define PRIzd "d" #define PRIzx "x" #elif SIZEOF_SIZE_T == 8 #define PRIzd "I64d" #define PRIzx "I64x" #else #error "weird sizeof size_t" #endif #elif COMPILER_IS_CLANG || COMPILER_IS_GNU /* print format specifier for size_t */ #define PRIzd "zd" #define PRIzx "zx" #else #error unknown compiler #endif #if HAVE_SNPRINTF #define wabt_snprintf snprintf #elif COMPILER_IS_MSVC /* can't just use _snprintf because it doesn't always null terminate */ #include int wabt_snprintf(char* str, size_t size, const char* format, ...); #else #error no snprintf #endif #if COMPILER_IS_MSVC /* can't just use vsnprintf because it doesn't always null terminate */ int wabt_vsnprintf(char* str, size_t size, const char* format, va_list ap); #else #define wabt_vsnprintf vsnprintf #endif #if !HAVE_SSIZE_T typedef int ssize_t; #endif #if !HAVE_STRCASECMP #if COMPILER_IS_MSVC #define strcasecmp _stricmp #else #error no strcasecmp #endif #endif #if COMPILER_IS_MSVC && defined(_M_X64) // MSVC on x64 generates uint64 -> float conversions but doesn't do // round-to-nearest-ties-to-even, which is required by WebAssembly. #include __inline double wabt_convert_uint64_to_double(unsigned __int64 x) { __m128d result = _mm_setzero_pd(); if (x & 0x8000000000000000ULL) { result = _mm_cvtsi64_sd(result, (x >> 1) | (x & 1)); result = _mm_add_sd(result, result); } else { result = _mm_cvtsi64_sd(result, x); } return _mm_cvtsd_f64(result); } __inline float wabt_convert_uint64_to_float(unsigned __int64 x) { __m128 result = _mm_setzero_ps(); if (x & 0x8000000000000000ULL) { result = _mm_cvtsi64_ss(result, (x >> 1) | (x & 1)); result = _mm_add_ss(result, result); } else { result = _mm_cvtsi64_ss(result, x); } return _mm_cvtss_f32(result); } #else #define wabt_convert_uint64_to_double(x) static_cast(x) #define wabt_convert_uint64_to_float(x) static_cast(x) #endif #endif /* WABT_CONFIG_H_ */