1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
# ------------------------------------------------------------------------------
# Compiler features definition and flags
# ------------------------------------------------------------------------------
set(
ALL_COMPILER_FEATURES
"builtin_ceil_floor_rint_trunc"
"builtin_fmax_fmin"
"builtin_fmaxf16_fminf16"
"builtin_round"
"builtin_roundeven"
"float16"
"float16_conversion"
"float128"
"fixed_point"
"cfloat16"
"cfloat128"
)
# Making sure ALL_COMPILER_FEATURES is sorted.
list(SORT ALL_COMPILER_FEATURES)
# Compiler features that are unavailable on GPU targets with the in-tree Clang.
set(
CPU_ONLY_COMPILER_FEATURES
"float128"
)
# Function to check whether the compiler supports the provided set of features.
# Usage:
# compiler_supports(
# <output variable>
# <list of cpu features>
# )
function(compiler_supports output_var features)
_intersection(var "${LIBC_CPU_FEATURES}" "${features}")
if("${var}" STREQUAL "${features}")
set(${output_var} TRUE PARENT_SCOPE)
else()
unset(${output_var} PARENT_SCOPE)
endif()
endfunction()
# ------------------------------------------------------------------------------
# Internal helpers and utilities.
# ------------------------------------------------------------------------------
# Computes the intersection between two lists.
function(_intersection output_var list1 list2)
foreach(element IN LISTS list1)
if("${list2}" MATCHES "(^|;)${element}(;|$)")
list(APPEND tmp "${element}")
endif()
endforeach()
set(${output_var} ${tmp} PARENT_SCOPE)
endfunction()
set(AVAILABLE_COMPILER_FEATURES "")
# Try compile a C file to check if flag is supported.
foreach(feature IN LISTS ALL_COMPILER_FEATURES)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(compile_options ${LIBC_COMPILE_OPTIONS_NATIVE})
set(link_options "")
if(${feature} STREQUAL "fixed_point")
list(APPEND compile_options "-ffixed-point")
elseif(${feature} MATCHES "^builtin_" OR
${feature} STREQUAL "float16_conversion")
set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
set(link_options -nostdlib)
# The compiler might handle calls to math builtins by generating calls to
# the respective libc math functions, in which case we cannot use these
# builtins in our implementations of these functions. We check that this is
# not the case by trying to link an executable, since linking would fail due
# to unresolved references with -nostdlib if calls to libc functions were
# generated.
#
# We also had issues with soft-float float16 conversion functions using both
# compiler-rt and libgcc, so we also check whether we can convert from and
# to float16 without calls to compiler runtime functions by trying to link
# an executable with -nostdlib.
set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
endif()
if(LIBC_TARGET_OS_IS_GPU)
# CUDA shouldn't be required to build the libc, only to test it, so we can't
# try to build CUDA binaries here. Since GPU builds are always compiled with
# the in-tree Clang, we just hardcode which compiler features are available
# when targeting GPUs.
if(feature IN_LIST CPU_ONLY_COMPILER_FEATURES)
set(has_feature FALSE)
else()
set(has_feature TRUE)
endif()
else()
try_compile(
has_feature
${CMAKE_CURRENT_BINARY_DIR}/compiler_features
SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/compiler_features/check_${feature}.cpp
COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${compile_options}
LINK_OPTIONS ${link_options}
)
endif()
if(has_feature)
list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
if(${feature} STREQUAL "float16")
set(LIBC_TYPES_HAS_FLOAT16 TRUE)
elseif(${feature} STREQUAL "float16_conversion")
add_compile_definitions(__LIBC_USE_FLOAT16_CONVERSION)
elseif(${feature} STREQUAL "float128")
set(LIBC_TYPES_HAS_FLOAT128 TRUE)
elseif(${feature} STREQUAL "fixed_point")
set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
elseif(${feature} STREQUAL "cfloat16")
set(LIBC_TYPES_HAS_CFLOAT16 TRUE)
elseif(${feature} STREQUAL "cfloat128")
set(LIBC_TYPES_HAS_CFLOAT128 TRUE)
elseif(${feature} STREQUAL "builtin_ceil_floor_rint_trunc")
set(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC TRUE)
elseif(${feature} STREQUAL "builtin_fmax_fmin")
set(LIBC_COMPILER_HAS_BUILTIN_FMAX_FMIN TRUE)
elseif(${feature} STREQUAL "builtin_fmaxf16_fminf16")
set(LIBC_COMPILER_HAS_BUILTIN_FMAXF16_FMINF16 TRUE)
elseif(${feature} STREQUAL "builtin_round")
set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE)
elseif(${feature} STREQUAL "builtin_roundeven")
set(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN TRUE)
endif()
endif()
endforeach()
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
set(link_options "")
message(STATUS "Compiler features available: ${AVAILABLE_COMPILER_FEATURES}")
### Compiler Feature Detection ###
# clang-8+, gcc-12+
check_cxx_compiler_flag("-ftrivial-auto-var-init=pattern" LIBC_CC_SUPPORTS_PATTERN_INIT)
# clang-6+, gcc-13+
check_cxx_compiler_flag("-nostdlib++" LIBC_CC_SUPPORTS_NOSTDLIBPP)
# clang-3.0+
check_cxx_compiler_flag("-nostdlibinc" LIBC_CC_SUPPORTS_NOSTDLIBINC)
|