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