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