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