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