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