10b57cec5SDimitry Andric //===-- int_lib.h - configuration header for compiler-rt -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file is a configuration header for compiler-rt. 100b57cec5SDimitry Andric // This file is not part of the interface of this library. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef INT_LIB_H 150b57cec5SDimitry Andric #define INT_LIB_H 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric // Assumption: Signed integral is 2's complement. 180b57cec5SDimitry Andric // Assumption: Right shift of signed negative is arithmetic shift. 190b57cec5SDimitry Andric // Assumption: Endianness is little or big (not mixed). 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric // ABI macro definitions 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric #if __ARM_EABI__ 2471daeec7SDimitry Andric #if defined(COMPILER_RT_ARMHF_TARGET) || (!defined(__clang__) && \ 2571daeec7SDimitry Andric defined(__GNUC__) && (__GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ < 5)) 2671daeec7SDimitry Andric // The pcs attribute was introduced in GCC 4.5.0 270b57cec5SDimitry Andric #define COMPILER_RT_ABI 280b57cec5SDimitry Andric #else 290b57cec5SDimitry Andric #define COMPILER_RT_ABI __attribute__((__pcs__("aapcs"))) 300b57cec5SDimitry Andric #endif 310b57cec5SDimitry Andric #else 320b57cec5SDimitry Andric #define COMPILER_RT_ABI 330b57cec5SDimitry Andric #endif 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric #define AEABI_RTABI __attribute__((__pcs__("aapcs"))) 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric #if defined(_MSC_VER) && !defined(__clang__) 380b57cec5SDimitry Andric #define ALWAYS_INLINE __forceinline 390b57cec5SDimitry Andric #define NOINLINE __declspec(noinline) 400b57cec5SDimitry Andric #define NORETURN __declspec(noreturn) 410b57cec5SDimitry Andric #define UNUSED 420b57cec5SDimitry Andric #else 430b57cec5SDimitry Andric #define ALWAYS_INLINE __attribute__((always_inline)) 440b57cec5SDimitry Andric #define NOINLINE __attribute__((noinline)) 450b57cec5SDimitry Andric #define NORETURN __attribute__((noreturn)) 460b57cec5SDimitry Andric #define UNUSED __attribute__((unused)) 470b57cec5SDimitry Andric #endif 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric #define STR(a) #a 500b57cec5SDimitry Andric #define XSTR(a) STR(a) 510b57cec5SDimitry Andric #define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name 520b57cec5SDimitry Andric 535ffd83dbSDimitry Andric #if defined(__ELF__) || defined(__MINGW32__) || defined(__wasm__) || \ 545f757f3fSDimitry Andric defined(_AIX) || defined(__CYGWIN__) 550b57cec5SDimitry Andric #define COMPILER_RT_ALIAS(name, aliasname) \ 560b57cec5SDimitry Andric COMPILER_RT_ABI __typeof(name) aliasname __attribute__((__alias__(#name))); 570b57cec5SDimitry Andric #elif defined(__APPLE__) 585ffd83dbSDimitry Andric #if defined(VISIBILITY_HIDDEN) 595ffd83dbSDimitry Andric #define COMPILER_RT_ALIAS_VISIBILITY(name) \ 605ffd83dbSDimitry Andric __asm__(".private_extern " SYMBOL_NAME(name)); 615ffd83dbSDimitry Andric #else 625ffd83dbSDimitry Andric #define COMPILER_RT_ALIAS_VISIBILITY(name) 635ffd83dbSDimitry Andric #endif 640b57cec5SDimitry Andric #define COMPILER_RT_ALIAS(name, aliasname) \ 650b57cec5SDimitry Andric __asm__(".globl " SYMBOL_NAME(aliasname)); \ 665ffd83dbSDimitry Andric COMPILER_RT_ALIAS_VISIBILITY(aliasname) \ 670b57cec5SDimitry Andric __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \ 680b57cec5SDimitry Andric COMPILER_RT_ABI __typeof(name) aliasname; 690b57cec5SDimitry Andric #elif defined(_WIN32) 700b57cec5SDimitry Andric #define COMPILER_RT_ALIAS(name, aliasname) 710b57cec5SDimitry Andric #else 720b57cec5SDimitry Andric #error Unsupported target 730b57cec5SDimitry Andric #endif 740b57cec5SDimitry Andric 75fe6060f1SDimitry Andric #if (defined(__FreeBSD__) || defined(__NetBSD__)) && \ 76fe6060f1SDimitry Andric (defined(_KERNEL) || defined(_STANDALONE)) 770b57cec5SDimitry Andric // 780b57cec5SDimitry Andric // Kernel and boot environment can't use normal headers, 790b57cec5SDimitry Andric // so use the equivalent system headers. 80fe6060f1SDimitry Andric // NB: FreeBSD (and OpenBSD) deprecate machine/limits.h in 81fe6060f1SDimitry Andric // favour of sys/limits.h, so prefer the former, but fall 82fe6060f1SDimitry Andric // back on the latter if not available since NetBSD only has 83fe6060f1SDimitry Andric // the latter. 840b57cec5SDimitry Andric // 85fe6060f1SDimitry Andric #if defined(__has_include) && __has_include(<sys/limits.h>) 86dd6565b7SDimitry Andric #include <sys/limits.h> 87dd6565b7SDimitry Andric #else 880b57cec5SDimitry Andric #include <machine/limits.h> 89dd6565b7SDimitry Andric #endif 900b57cec5SDimitry Andric #include <sys/stdint.h> 910b57cec5SDimitry Andric #include <sys/types.h> 920b57cec5SDimitry Andric #else 930b57cec5SDimitry Andric // Include the standard compiler builtin headers we use functionality from. 940b57cec5SDimitry Andric #include <float.h> 950b57cec5SDimitry Andric #include <limits.h> 960b57cec5SDimitry Andric #include <stdbool.h> 970b57cec5SDimitry Andric #include <stdint.h> 980b57cec5SDimitry Andric #endif 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric // Include the commonly used internal type definitions. 1010b57cec5SDimitry Andric #include "int_types.h" 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // Include internal utility function declarations. 1040b57cec5SDimitry Andric #include "int_util.h" 1050b57cec5SDimitry Andric 1065ffd83dbSDimitry Andric COMPILER_RT_ABI int __paritysi2(si_int a); 1075ffd83dbSDimitry Andric COMPILER_RT_ABI int __paritydi2(di_int a); 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b); 1100b57cec5SDimitry Andric COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b); 1110b57cec5SDimitry Andric COMPILER_RT_ABI su_int __udivsi3(su_int n, su_int d); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric COMPILER_RT_ABI su_int __udivmodsi4(su_int a, su_int b, su_int *rem); 1140b57cec5SDimitry Andric COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem); 1150b57cec5SDimitry Andric #ifdef CRT_HAS_128BIT 1165ffd83dbSDimitry Andric COMPILER_RT_ABI int __clzti2(ti_int a); 1170b57cec5SDimitry Andric COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem); 1180b57cec5SDimitry Andric #endif 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // Definitions for builtins unavailable on MSVC 1210b57cec5SDimitry Andric #if defined(_MSC_VER) && !defined(__clang__) 1220b57cec5SDimitry Andric #include <intrin.h> 1230b57cec5SDimitry Andric 124*7a6dacacSDimitry Andric static int __inline __builtin_ctz(uint32_t value) { 1250b57cec5SDimitry Andric unsigned long trailing_zero = 0; 1260b57cec5SDimitry Andric if (_BitScanForward(&trailing_zero, value)) 1270b57cec5SDimitry Andric return trailing_zero; 1280b57cec5SDimitry Andric return 32; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 131*7a6dacacSDimitry Andric static int __inline __builtin_clz(uint32_t value) { 1320b57cec5SDimitry Andric unsigned long leading_zero = 0; 1330b57cec5SDimitry Andric if (_BitScanReverse(&leading_zero, value)) 1340b57cec5SDimitry Andric return 31 - leading_zero; 1350b57cec5SDimitry Andric return 32; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric #if defined(_M_ARM) || defined(_M_X64) 139*7a6dacacSDimitry Andric static int __inline __builtin_clzll(uint64_t value) { 1400b57cec5SDimitry Andric unsigned long leading_zero = 0; 1410b57cec5SDimitry Andric if (_BitScanReverse64(&leading_zero, value)) 1420b57cec5SDimitry Andric return 63 - leading_zero; 1430b57cec5SDimitry Andric return 64; 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric #else 146*7a6dacacSDimitry Andric static int __inline __builtin_clzll(uint64_t value) { 1470b57cec5SDimitry Andric if (value == 0) 1480b57cec5SDimitry Andric return 64; 1490b57cec5SDimitry Andric uint32_t msh = (uint32_t)(value >> 32); 1500b57cec5SDimitry Andric uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); 1510b57cec5SDimitry Andric if (msh != 0) 1520b57cec5SDimitry Andric return __builtin_clz(msh); 1530b57cec5SDimitry Andric return 32 + __builtin_clz(lsh); 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric #endif 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric #define __builtin_clzl __builtin_clzll 158fe6060f1SDimitry Andric 159*7a6dacacSDimitry Andric static bool __inline __builtin_sadd_overflow(int x, int y, int *result) { 160fe6060f1SDimitry Andric if ((x < 0) != (y < 0)) { 161fe6060f1SDimitry Andric *result = x + y; 162fe6060f1SDimitry Andric return false; 163fe6060f1SDimitry Andric } 164fe6060f1SDimitry Andric int tmp = (unsigned int)x + (unsigned int)y; 165fe6060f1SDimitry Andric if ((tmp < 0) != (x < 0)) 166fe6060f1SDimitry Andric return true; 167fe6060f1SDimitry Andric *result = tmp; 168fe6060f1SDimitry Andric return false; 169fe6060f1SDimitry Andric } 170fe6060f1SDimitry Andric 1710b57cec5SDimitry Andric #endif // defined(_MSC_VER) && !defined(__clang__) 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric #endif // INT_LIB_H 174