tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cpu.h (9204B)


      1 // Copyright 2022 Google Inc. All Rights Reserved.
      2 //
      3 // Use of this source code is governed by a BSD-style license
      4 // that can be found in the COPYING file in the root of the source
      5 // tree. An additional intellectual property rights grant can be found
      6 // in the file PATENTS. All contributing project authors may
      7 // be found in the AUTHORS file in the root of the source tree.
      8 // -----------------------------------------------------------------------------
      9 //
     10 //   CPU detection functions and macros.
     11 //
     12 // Author: Skal (pascal.massimino@gmail.com)
     13 
     14 #ifndef WEBP_DSP_CPU_H_
     15 #define WEBP_DSP_CPU_H_
     16 
     17 #include <stddef.h>
     18 
     19 #ifdef HAVE_CONFIG_H
     20 #include "src/webp/config.h"
     21 #endif
     22 
     23 #include "src/webp/types.h"
     24 
     25 #if defined(__GNUC__)
     26 #define LOCAL_GCC_VERSION ((__GNUC__ << 8) | __GNUC_MINOR__)
     27 #define LOCAL_GCC_PREREQ(maj, min) (LOCAL_GCC_VERSION >= (((maj) << 8) | (min)))
     28 #else
     29 #define LOCAL_GCC_VERSION 0
     30 #define LOCAL_GCC_PREREQ(maj, min) 0
     31 #endif
     32 
     33 #if defined(__clang__)
     34 #define LOCAL_CLANG_VERSION ((__clang_major__ << 8) | __clang_minor__)
     35 #define LOCAL_CLANG_PREREQ(maj, min) \
     36  (LOCAL_CLANG_VERSION >= (((maj) << 8) | (min)))
     37 #else
     38 #define LOCAL_CLANG_VERSION 0
     39 #define LOCAL_CLANG_PREREQ(maj, min) 0
     40 #endif
     41 
     42 #ifndef __has_builtin
     43 #define __has_builtin(x) 0
     44 #endif
     45 
     46 //------------------------------------------------------------------------------
     47 // x86 defines.
     48 
     49 #if !defined(HAVE_CONFIG_H)
     50 #if defined(_MSC_VER) && _MSC_VER > 1310 && \
     51    (defined(_M_X64) || defined(_M_IX86))
     52 #define WEBP_MSC_SSE2  // Visual C++ SSE2 targets
     53 #endif
     54 
     55 #if defined(_MSC_VER) && _MSC_VER >= 1500 && \
     56    (defined(_M_X64) || defined(_M_IX86))
     57 #define WEBP_MSC_SSE41  // Visual C++ SSE4.1 targets
     58 #endif
     59 
     60 #if defined(_MSC_VER) && _MSC_VER >= 1700 && \
     61    (defined(_M_X64) || defined(_M_IX86))
     62 #define WEBP_MSC_AVX2  // Visual C++ AVX2 targets
     63 #endif
     64 #endif
     65 
     66 // WEBP_HAVE_* are used to indicate the presence of the instruction set in dsp
     67 // files without intrinsics, allowing the corresponding Init() to be called.
     68 // Files containing intrinsics will need to be built targeting the instruction
     69 // set so should succeed on one of the earlier tests.
     70 #if (defined(__SSE2__) || defined(WEBP_MSC_SSE2)) && \
     71    (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE2))
     72 #define WEBP_USE_SSE2
     73 #endif
     74 
     75 #if defined(WEBP_USE_SSE2) && !defined(WEBP_HAVE_SSE2)
     76 #define WEBP_HAVE_SSE2
     77 #endif
     78 
     79 #if (defined(__SSE4_1__) || defined(WEBP_MSC_SSE41)) && \
     80    (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_SSE41))
     81 #define WEBP_USE_SSE41
     82 #endif
     83 
     84 #if defined(WEBP_USE_SSE41) && !defined(WEBP_HAVE_SSE41)
     85 #define WEBP_HAVE_SSE41
     86 #endif
     87 
     88 #if (defined(__AVX2__) || defined(WEBP_MSC_AVX2)) && \
     89    (defined(WEBP_HAVE_AVX2))
     90 #define WEBP_USE_AVX2
     91 #endif
     92 
     93 #if defined(WEBP_USE_AVX2) && !defined(WEBP_HAVE_AVX2)
     94 #define WEBP_HAVE_AVX2
     95 #endif
     96 
     97 #undef WEBP_MSC_AVX2
     98 #undef WEBP_MSC_SSE41
     99 #undef WEBP_MSC_SSE2
    100 
    101 //------------------------------------------------------------------------------
    102 // Arm defines.
    103 
    104 // The intrinsics currently cause compiler errors with arm-nacl-gcc and the
    105 // inline assembly would need to be modified for use with Native Client.
    106 #if ((defined(__ARM_NEON__) || defined(__aarch64__)) &&       \
    107     (!defined(HAVE_CONFIG_H) || defined(WEBP_HAVE_NEON))) && \
    108    !defined(__native_client__)
    109 #define WEBP_USE_NEON
    110 #endif
    111 
    112 #if !defined(WEBP_USE_NEON) && defined(__ANDROID__) && \
    113    defined(__ARM_ARCH_7A__) && defined(HAVE_CPU_FEATURES_H)
    114 #define WEBP_ANDROID_NEON  // Android targets that may have NEON
    115 #define WEBP_USE_NEON
    116 #endif
    117 
    118 // Note: ARM64 is supported in Visual Studio 2017, but requires the direct
    119 // inclusion of arm64_neon.h; Visual Studio 2019 includes this file in
    120 // arm_neon.h. Compile errors were seen with Visual Studio 2019 16.4 with
    121 // vtbl4_u8(); a fix was made in 16.6.
    122 #if defined(_MSC_VER) && \
    123    ((_MSC_VER >= 1700 && defined(_M_ARM)) || \
    124     (_MSC_VER >= 1926 && (defined(_M_ARM64) || defined(_M_ARM64EC))))
    125 #define WEBP_USE_NEON
    126 #define WEBP_USE_INTRINSICS
    127 #endif
    128 
    129 #if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
    130 #define WEBP_AARCH64 1
    131 #else
    132 #define WEBP_AARCH64 0
    133 #endif
    134 
    135 #if defined(WEBP_USE_NEON) && !defined(WEBP_HAVE_NEON)
    136 #define WEBP_HAVE_NEON
    137 #endif
    138 
    139 //------------------------------------------------------------------------------
    140 // MIPS defines.
    141 
    142 #if defined(__mips__) && !defined(__mips64) && defined(__mips_isa_rev) && \
    143    (__mips_isa_rev >= 1) && (__mips_isa_rev < 6)
    144 #define WEBP_USE_MIPS32
    145 #if (__mips_isa_rev >= 2)
    146 #define WEBP_USE_MIPS32_R2
    147 #if defined(__mips_dspr2) || (defined(__mips_dsp_rev) && __mips_dsp_rev >= 2)
    148 #define WEBP_USE_MIPS_DSP_R2
    149 #endif
    150 #endif
    151 #endif
    152 
    153 #if defined(__mips_msa) && defined(__mips_isa_rev) && (__mips_isa_rev >= 5)
    154 #define WEBP_USE_MSA
    155 #endif
    156 
    157 //------------------------------------------------------------------------------
    158 
    159 #ifndef WEBP_DSP_OMIT_C_CODE
    160 #define WEBP_DSP_OMIT_C_CODE 1
    161 #endif
    162 
    163 #if defined(WEBP_USE_NEON) && WEBP_DSP_OMIT_C_CODE
    164 #define WEBP_NEON_OMIT_C_CODE 1
    165 #else
    166 #define WEBP_NEON_OMIT_C_CODE 0
    167 #endif
    168 
    169 #if !(LOCAL_CLANG_PREREQ(3, 8) || LOCAL_GCC_PREREQ(4, 8) || WEBP_AARCH64)
    170 #define WEBP_NEON_WORK_AROUND_GCC 1
    171 #else
    172 #define WEBP_NEON_WORK_AROUND_GCC 0
    173 #endif
    174 
    175 //------------------------------------------------------------------------------
    176 
    177 // This macro prevents thread_sanitizer from reporting known concurrent writes.
    178 #define WEBP_TSAN_IGNORE_FUNCTION
    179 #if defined(__has_feature)
    180 #if __has_feature(thread_sanitizer)
    181 #undef WEBP_TSAN_IGNORE_FUNCTION
    182 #define WEBP_TSAN_IGNORE_FUNCTION __attribute__((no_sanitize_thread))
    183 #endif
    184 #endif
    185 
    186 #if defined(__has_feature)
    187 #if __has_feature(memory_sanitizer)
    188 #define WEBP_MSAN
    189 #endif
    190 #endif
    191 
    192 #if defined(WEBP_USE_THREAD) && !defined(_WIN32)
    193 #include <pthread.h>  // NOLINT
    194 
    195 #define WEBP_DSP_INIT(func)                                         \
    196  do {                                                              \
    197    static volatile VP8CPUInfo func##_last_cpuinfo_used =           \
    198        (VP8CPUInfo)&func##_last_cpuinfo_used;                      \
    199    static pthread_mutex_t func##_lock = PTHREAD_MUTEX_INITIALIZER; \
    200    if (pthread_mutex_lock(&func##_lock)) break;                    \
    201    if (func##_last_cpuinfo_used != VP8GetCPUInfo) func();          \
    202    func##_last_cpuinfo_used = VP8GetCPUInfo;                       \
    203    (void)pthread_mutex_unlock(&func##_lock);                       \
    204  } while (0)
    205 #else  // !(defined(WEBP_USE_THREAD) && !defined(_WIN32))
    206 #define WEBP_DSP_INIT(func)                               \
    207  do {                                                    \
    208    static volatile VP8CPUInfo func##_last_cpuinfo_used = \
    209        (VP8CPUInfo)&func##_last_cpuinfo_used;            \
    210    if (func##_last_cpuinfo_used == VP8GetCPUInfo) break; \
    211    func();                                               \
    212    func##_last_cpuinfo_used = VP8GetCPUInfo;             \
    213  } while (0)
    214 #endif  // defined(WEBP_USE_THREAD) && !defined(_WIN32)
    215 
    216 // Defines an Init + helper function that control multiple initialization of
    217 // function pointers / tables.
    218 /* Usage:
    219   WEBP_DSP_INIT_FUNC(InitFunc) {
    220     ...function body
    221   }
    222 */
    223 #define WEBP_DSP_INIT_FUNC(name)                                            \
    224  static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void);                  \
    225  WEBP_TSAN_IGNORE_FUNCTION void name(void) { WEBP_DSP_INIT(name##_body); } \
    226  static WEBP_TSAN_IGNORE_FUNCTION void name##_body(void)
    227 
    228 #define WEBP_UBSAN_IGNORE_UNDEF
    229 #define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
    230 #if defined(__clang__) && defined(__has_attribute)
    231 #if __has_attribute(no_sanitize)
    232 // This macro prevents the undefined behavior sanitizer from reporting
    233 // failures. This is only meant to silence unaligned loads on platforms that
    234 // are known to support them.
    235 #undef WEBP_UBSAN_IGNORE_UNDEF
    236 #define WEBP_UBSAN_IGNORE_UNDEF __attribute__((no_sanitize("undefined")))
    237 
    238 // This macro prevents the undefined behavior sanitizer from reporting
    239 // failures related to unsigned integer overflows. This is only meant to
    240 // silence cases where this well defined behavior is expected.
    241 #undef WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW
    242 #define WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW \
    243  __attribute__((no_sanitize("unsigned-integer-overflow")))
    244 #endif
    245 #endif
    246 
    247 // If 'ptr' is NULL, returns NULL. Otherwise returns 'ptr + off'.
    248 // Prevents undefined behavior sanitizer nullptr-with-nonzero-offset warning.
    249 #if !defined(WEBP_OFFSET_PTR)
    250 #define WEBP_OFFSET_PTR(ptr, off) (((ptr) == NULL) ? NULL : ((ptr) + (off)))
    251 #endif
    252 
    253 // Regularize the definition of WEBP_SWAP_16BIT_CSP (backward compatibility)
    254 #if !defined(WEBP_SWAP_16BIT_CSP)
    255 #define WEBP_SWAP_16BIT_CSP 0
    256 #endif
    257 
    258 // some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__)
    259 #if !defined(WORDS_BIGENDIAN) &&                   \
    260    (defined(__BIG_ENDIAN__) || defined(_M_PPC) || \
    261     (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)))
    262 #define WORDS_BIGENDIAN
    263 #endif
    264 
    265 typedef enum {
    266  kSSE2,
    267  kSSE3,
    268  kSlowSSSE3,  // special feature for slow SSSE3 architectures
    269  kSSE4_1,
    270  kAVX,
    271  kAVX2,
    272  kNEON,
    273  kMIPS32,
    274  kMIPSdspR2,
    275  kMSA
    276 } CPUFeature;
    277 
    278 // returns true if the CPU supports the feature.
    279 typedef int (*VP8CPUInfo)(CPUFeature feature);
    280 
    281 #endif  // WEBP_DSP_CPU_H_