Home | History | Annotate | Line # | Download | only in common
      1 /*
      2  * Copyright (c) Meta Platforms, Inc. and affiliates.
      3  * All rights reserved.
      4  *
      5  * This source code is licensed under both the BSD-style license (found in the
      6  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
      7  * in the COPYING file in the root directory of this source tree).
      8  * You may select, at your option, one of the above-listed licenses.
      9  */
     10 
     11 #ifndef ZSTD_PORTABILITY_MACROS_H
     12 #define ZSTD_PORTABILITY_MACROS_H
     13 
     14 /**
     15  * This header file contains macro definitions to support portability.
     16  * This header is shared between C and ASM code, so it MUST only
     17  * contain macro definitions. It MUST not contain any C code.
     18  *
     19  * This header ONLY defines macros to detect platforms/feature support.
     20  *
     21  */
     22 
     23 
     24 /* compat. with non-clang compilers */
     25 #ifndef __has_attribute
     26   #define __has_attribute(x) 0
     27 #endif
     28 
     29 /* compat. with non-clang compilers */
     30 #ifndef __has_builtin
     31 #  define __has_builtin(x) 0
     32 #endif
     33 
     34 /* compat. with non-clang compilers */
     35 #ifndef __has_feature
     36 #  define __has_feature(x) 0
     37 #endif
     38 
     39 /* detects whether we are being compiled under msan */
     40 #ifndef ZSTD_MEMORY_SANITIZER
     41 #  if __has_feature(memory_sanitizer)
     42 #    define ZSTD_MEMORY_SANITIZER 1
     43 #  else
     44 #    define ZSTD_MEMORY_SANITIZER 0
     45 #  endif
     46 #endif
     47 
     48 /* detects whether we are being compiled under asan */
     49 #ifndef ZSTD_ADDRESS_SANITIZER
     50 #  if __has_feature(address_sanitizer)
     51 #    define ZSTD_ADDRESS_SANITIZER 1
     52 #  elif defined(__SANITIZE_ADDRESS__)
     53 #    define ZSTD_ADDRESS_SANITIZER 1
     54 #  else
     55 #    define ZSTD_ADDRESS_SANITIZER 0
     56 #  endif
     57 #endif
     58 
     59 /* detects whether we are being compiled under dfsan */
     60 #ifndef ZSTD_DATAFLOW_SANITIZER
     61 # if __has_feature(dataflow_sanitizer)
     62 #  define ZSTD_DATAFLOW_SANITIZER 1
     63 # else
     64 #  define ZSTD_DATAFLOW_SANITIZER 0
     65 # endif
     66 #endif
     67 
     68 /* Mark the internal assembly functions as hidden  */
     69 #ifdef __ELF__
     70 # define ZSTD_HIDE_ASM_FUNCTION(func) .hidden func
     71 #elif defined(__APPLE__)
     72 # define ZSTD_HIDE_ASM_FUNCTION(func) .private_extern func
     73 #else
     74 # define ZSTD_HIDE_ASM_FUNCTION(func)
     75 #endif
     76 
     77 /* Compile time determination of BMI2 support */
     78 #ifndef STATIC_BMI2
     79 #  if defined(__BMI2__)
     80 #    define STATIC_BMI2 1
     81 #  elif defined(_MSC_VER) && defined(__AVX2__)
     82 #    define STATIC_BMI2 1 /* MSVC does not have a BMI2 specific flag, but every CPU that supports AVX2 also supports BMI2 */
     83 #  endif
     84 #endif
     85 
     86 #ifndef STATIC_BMI2
     87 #  define STATIC_BMI2 0
     88 #endif
     89 
     90 /* Enable runtime BMI2 dispatch based on the CPU.
     91  * Enabled for clang & gcc >=4.8 on x86 when BMI2 isn't enabled by default.
     92  */
     93 #ifndef DYNAMIC_BMI2
     94 #  if ((defined(__clang__) && __has_attribute(__target__)) \
     95       || (defined(__GNUC__) \
     96           && (__GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))) \
     97       && (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)) \
     98       && !defined(__BMI2__)
     99 #    define DYNAMIC_BMI2 1
    100 #  else
    101 #    define DYNAMIC_BMI2 0
    102 #  endif
    103 #endif
    104 
    105 /**
    106  * Only enable assembly for GNU C compatible compilers,
    107  * because other platforms may not support GAS assembly syntax.
    108  *
    109  * Only enable assembly for Linux / MacOS / Win32, other platforms may
    110  * work, but they haven't been tested. This could likely be
    111  * extended to BSD systems.
    112  *
    113  * Disable assembly when MSAN is enabled, because MSAN requires
    114  * 100% of code to be instrumented to work.
    115  */
    116 #if defined(__GNUC__)
    117 #  if defined(__linux__) || defined(__linux) || defined(__APPLE__) || defined(_WIN32)
    118 #    if ZSTD_MEMORY_SANITIZER
    119 #      define ZSTD_ASM_SUPPORTED 0
    120 #    elif ZSTD_DATAFLOW_SANITIZER
    121 #      define ZSTD_ASM_SUPPORTED 0
    122 #    else
    123 #      define ZSTD_ASM_SUPPORTED 1
    124 #    endif
    125 #  else
    126 #    define ZSTD_ASM_SUPPORTED 0
    127 #  endif
    128 #else
    129 #  define ZSTD_ASM_SUPPORTED 0
    130 #endif
    131 
    132 /**
    133  * Determines whether we should enable assembly for x86-64
    134  * with BMI2.
    135  *
    136  * Enable if all of the following conditions hold:
    137  * - ASM hasn't been explicitly disabled by defining ZSTD_DISABLE_ASM
    138  * - Assembly is supported
    139  * - We are compiling for x86-64 and either:
    140  *   - DYNAMIC_BMI2 is enabled
    141  *   - BMI2 is supported at compile time
    142  */
    143 #if !defined(ZSTD_DISABLE_ASM) &&                                 \
    144     ZSTD_ASM_SUPPORTED &&                                         \
    145     defined(__x86_64__) &&                                        \
    146     (DYNAMIC_BMI2 || defined(__BMI2__))
    147 # define ZSTD_ENABLE_ASM_X86_64_BMI2 1
    148 #else
    149 # define ZSTD_ENABLE_ASM_X86_64_BMI2 0
    150 #endif
    151 
    152 /*
    153  * For x86 ELF targets, add .note.gnu.property section for Intel CET in
    154  * assembly sources when CET is enabled.
    155  *
    156  * Additionally, any function that may be called indirectly must begin
    157  * with ZSTD_CET_ENDBRANCH.
    158  */
    159 #if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__)) \
    160     && defined(__has_include)
    161 # if __has_include(<cet.h>)
    162 #  include <cet.h>
    163 #  define ZSTD_CET_ENDBRANCH _CET_ENDBR
    164 # endif
    165 #endif
    166 
    167 #ifndef ZSTD_CET_ENDBRANCH
    168 # define ZSTD_CET_ENDBRANCH
    169 #endif
    170 
    171 #endif /* ZSTD_PORTABILITY_MACROS_H */
    172